mirror of
https://github.com/muerwre/muerwre.github.io.git
synced 2025-04-25 02:46:39 +07:00
added whole content
This commit is contained in:
parent
1b5df685cb
commit
8b25e0631a
70 changed files with 5962 additions and 19 deletions
248
content/Blockchain/Smart contracts.md
Normal file
248
content/Blockchain/Smart contracts.md
Normal file
|
@ -0,0 +1,248 @@
|
|||
For common functions see [Common typescript examples](Common%20typescript%20examples.md).
|
||||
|
||||
## Getting smart contract instance
|
||||
|
||||
Useful for calling smart contract methods:
|
||||
|
||||
```typescript
|
||||
import { Contract } from 'web3-eth-contract';
|
||||
import { web3 } from '.';
|
||||
|
||||
const getContract = (abi: object, address?: string): Contract => {
|
||||
const abiFromJson = JSON.parse(JSON.stringify(abi));
|
||||
return new web3.eth.Contract(abiFromJson, address);
|
||||
};
|
||||
|
||||
export default getContract;
|
||||
```
|
||||
## Executing contract method
|
||||
|
||||
Contract has **read** and **write** methods. To get a list of methods, you can paste contract address on [https://etherscan.io/ ETH](https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7#readContract) or any other service.
|
||||
|
||||
**Read** methods doesn't require spending **gas**. **Write** methods cost some amount of **gas**, hence they will be executed with confirmation from user.
|
||||
|
||||
### Example for #Metamask without private key
|
||||
|
||||
```typescript
|
||||
// see example below
|
||||
import { getContract } from '.';
|
||||
|
||||
// ABI of contract
|
||||
const CONTRACT_ABI = { /* ... */ };
|
||||
// address for contract
|
||||
const CONTRACT_ADDRESS = '0xdea164f67df4dbfe675d5271c9d404e0260f33bb';
|
||||
|
||||
export const executeContractMethod = async ({}) => {
|
||||
// getting contract
|
||||
const contract = getContract(CONTRACT_ABI, CONTRACT_ADDRESS);
|
||||
|
||||
// Calling write method
|
||||
try {
|
||||
// authorizing with Metamask
|
||||
await web3.currentProvider.request({ method: 'eth_requestAccounts' });
|
||||
// getting wallet address
|
||||
const addressUser = web3.currentProvider.selectedAddress;
|
||||
// calling "store" store method for contract
|
||||
// payload should include `from` address, that matches
|
||||
// current user's wallet
|
||||
await contract.methods.store(0, 'Parameter').send({
|
||||
from: addressUser,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
// calling read method
|
||||
try {
|
||||
// this method can return data
|
||||
const result = await contract.methods.retrieve().call();
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Node.js and React Native example
|
||||
|
||||
```typescript
|
||||
// see example below
|
||||
import { getContract } from '.';
|
||||
|
||||
// ABI контракта
|
||||
const CONTRACT_ABI = { /* ... */ };
|
||||
// contract address
|
||||
const CONTRACT_ADDRESS = '0xdea164f67df4dbfe675d5271c9d404e0260f33bb';
|
||||
// getting contract
|
||||
const contract = getContract(CONTRACT_ABI, CONTRACT_ADDRESS);
|
||||
// account's private key
|
||||
const privateKey = '...';
|
||||
|
||||
// write-methods requires private key
|
||||
const executeContractMethod = async (val: number) => {
|
||||
const transaction = contract.methods.store(val);
|
||||
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
|
||||
const options = {
|
||||
to: CONTRACT_ADDRESS,
|
||||
data: transaction.encodeABI(),
|
||||
gas: await transaction.estimateGas({ from: account.address }),
|
||||
gasPrice: await web3.eth.getGasPrice(),
|
||||
};
|
||||
const signed = await web3.eth.accounts.signTransaction(
|
||||
options,
|
||||
privateKey,
|
||||
);
|
||||
await web3.eth.sendSignedTransaction(signed.rawTransaction!);
|
||||
};
|
||||
```
|
||||
|
||||
### Calling a batch of contract's methods
|
||||
|
||||
Function calls batch of requests, returning array of results. For example:
|
||||
|
||||
```typescript
|
||||
const requests = [
|
||||
contract.method.balanceOf().call,
|
||||
contract.method.getStaked().call
|
||||
]
|
||||
|
||||
const result = await makeBatchRequest(request);
|
||||
```
|
||||
|
||||
```typescript
|
||||
const web3 = new Web3(Web3.givenProvider || PROVIDER_URL);
|
||||
|
||||
const makeBatchRequest = (calls: any[]) => {
|
||||
try {
|
||||
const web3 = getWeb3NoAccount();
|
||||
const batch = new web3.BatchRequest();
|
||||
|
||||
const promises = calls.map((call) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
batch.add(
|
||||
call.request({}, (err, result) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
batch.execute();
|
||||
|
||||
return Promise.all(promises);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export default makeBatchRequest;
|
||||
```
|
||||
|
||||
## Subscribing to smart contract events
|
||||
|
||||
There're different ways to subscribe for contract events. For all of them you will need following variables:
|
||||
|
||||
```typescript
|
||||
import Web3 from 'web3';
|
||||
const web3 = new Web3('YOUR_RPC_ENDPOINT_HERE');
|
||||
const ABI = 'YOUR ABI HERE';
|
||||
const CONTRACT_ADDRESS = 'YOUR CONTRACT ADDRESS HERE';
|
||||
const myContract = new Web3.Contract(ABI, CONTRACT_ADDRESS);
|
||||
```
|
||||
|
||||
### By accessing contract.events
|
||||
|
||||
```typescript
|
||||
referralProgramContract.events
|
||||
.RegisterUser()
|
||||
.on('connected', (subscriptionId: string) => {
|
||||
console.log(`| UserRegistered | events | ${subscriptionId}`);
|
||||
})
|
||||
.on(
|
||||
'data',
|
||||
async (event: {
|
||||
removed: boolean;
|
||||
returnValues: RegisterUserResponseInterface;
|
||||
}) => {
|
||||
try {
|
||||
if (event.removed) {
|
||||
return;
|
||||
}
|
||||
const { user, referrer } = event.returnValues;
|
||||
console.log(user, referrer);
|
||||
} catch (e) {
|
||||
console.log(`| ONCE | ${e}`);
|
||||
}
|
||||
},
|
||||
)
|
||||
.on('error', (error: ErrnoException) => {
|
||||
console.log(error);
|
||||
});
|
||||
```
|
||||
|
||||
### With filtering
|
||||
|
||||
We're listening to `Transfer` event here:
|
||||
|
||||
```typescript
|
||||
let options = {
|
||||
filter: {
|
||||
value: [],
|
||||
},
|
||||
fromBlock: 0
|
||||
};
|
||||
|
||||
myContract.events.Transfer(options)
|
||||
.on('data', event => console.log(event))
|
||||
.on('changed', changed => console.log(changed))
|
||||
.on('error', err => throw err)
|
||||
.on('connected', str => console.log(str))
|
||||
```
|
||||
|
||||
### Common Subscribe method
|
||||
|
||||
Filtering options can also be specified:
|
||||
|
||||
```typescript
|
||||
let options = {
|
||||
fromBlock: 0,
|
||||
address: ['address-1', 'address-2'], //Only get events from specific addresses
|
||||
topics: [] //What topics to subscribe to
|
||||
};
|
||||
|
||||
let subscription = ('logs', options, (err,event) => {
|
||||
if (!err)
|
||||
console.log(event)
|
||||
});
|
||||
|
||||
subscription.on('data', event => console.log(event))
|
||||
subscription.on('changed', changed => console.log(changed))
|
||||
subscription.on('error', err => { throw err })
|
||||
subscription.on('connected', nr => console.log(nr))
|
||||
```
|
||||
|
||||
### Getting event history
|
||||
|
||||
Getting history for `Transfer` events for specific values. More info can be found [here](https://web3js.readthedocs.io/en/v1.2.11/web3-eth-subscribe.html#)
|
||||
|
||||
```typescript
|
||||
//example options(optional)
|
||||
let options = {
|
||||
filter: {
|
||||
// only get events where transfer value was 1000 or 1337
|
||||
value: ['1000', '1337']
|
||||
},
|
||||
// number | "earliest" | "pending" | "latest"
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
};
|
||||
|
||||
myContract.getPastEvents('Transfer', options)
|
||||
.then(results => console.log(results))
|
||||
.catch(err => throw err);
|
||||
|
||||
```
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue