This documentation provides a guide on how to transfer assets between wallets and to contracts using the SDK.
The account.transfer
method is used to initiate a transaction request that transfers an asset from one wallet to another. This method requires three parameters:
Upon execution, this function returns a promise that resolves to a transaction response. To wait for the transaction to be processed, call response.wait()
.
Here is an illustration on how to use the account.transfer
function:
// #import { Wallet, BN };
const sender = Wallet.fromPrivateKey('...');
const destination = Wallet.generate({
provider: sender.provider,
});
const amountToTransfer = 500;
const baseAssetId = await sender.provider.getBaseAssetId();
const response = await sender.transfer(destination.address, amountToTransfer, baseAssetId);
await response.wait();
// Retrieve balances
const receiverBalance = await destination.getBalance(baseAssetId);
// Validate new balance
expect(new BN(receiverBalance).toNumber()).toEqual(amountToTransfer);
In the previous example, we used the transfer
method, which essentially creates a ScriptTransactionRequest
, populates its data with the provided transfer information, and submits the transaction request to the node.
However, there may be times when you need the Transaction ID before actually submitting it to the node. To achieve this, you can simply call the createTransfer
method instead.
This method also creates a ScriptTransactionRequest
and populates it with the provided data, but instead of submitting it to the node, it returns the request.
const transactionRequest = await sender.createTransfer(
destination.address,
amountToTransfer,
assetId
);
const chainId = provider.getChainId();
const transactionId = transactionRequest.getTransactionId(chainId);
const response = await sender.sendTransaction(transactionRequest);
const { id } = await response.wait();
// The transaction id should is the same as the one returned by the transaction request
expect(id).toEqual(transactionId);
It's important to be aware that once you have this transaction request, any modifications made to it will result in a new and distinct transaction. Consequently, this will lead to a different transaction ID. Therefore, make sure to not changing the transaction request if you expects the ID to remain the same.
const transactionRequest = await sender.createTransfer(
destination.address,
amountToTransfer,
assetId
);
const chainId = provider.getChainId();
const transactionId = transactionRequest.getTransactionId(chainId);
transactionRequest.maturity = 1;
const { maxFee } = await provider.estimateTxGasAndFee({ transactionRequest });
transactionRequest.maxFee = maxFee;
const response = await sender.sendTransaction(transactionRequest);
const { id } = await response.wait();
expect(id).not.toEqual(transactionId);
When transferring assets to a deployed contract, we use the transferToContract
method. This method closely mirrors the account.transfer
method in terms of parameter structure.
However, instead of supplying the target wallet's address, as done in destination.address
for the transfer method, we need to provide an instance of Address created from the deployed contract id.
If you have the Contract instance of the deployed contract, you can simply use its id
property. However, if the contract was deployed with forc deploy
or not by you, you will likely only have its ID in a hex string format. In such cases, you can create an Address instance from the contract ID using Address.fromAddressOrString('0x123...')
.
Here's an example demonstrating how to use transferToContract
:
// #import { Wallet, BN };
const senderWallet = Wallet.fromPrivateKey('...');
const amountToTransfer = 400;
const assetId = provider.getBaseAssetId();
const contractId = Address.fromAddressOrString('0x123...');
const contractBalance = await deployedContract.getBalance(assetId);
const tx = await sender.transferToContract(contractId, amountToTransfer, assetId);
expect(new BN(contractBalance).toNumber()).toBe(0);
await tx.waitForResult();
expect(new BN(await deployedContract.getBalance(assetId)).toNumber()).toBe(amountToTransfer);
Remember to always invoke the waitForResult()
function on the transaction response. This ensures that the transaction has been successfully mined before proceeding.