NEAR
The NEAR part carries out the practice using naer-api-js. Please prepare by installing the package.
Create Signed transaction
For a signed transaction, there are three essential steps.
- Create a raw transaction first.
- Make a raw transaction signature.
- Convert a raw transaction into a signed transaction by adding a signature.
1. getNearTx
Transaction and signature are needed. We first develop a getNearTx
function to generate raw transaction because it is necessary to have a raw transaction to receive a signature via kms.
You can specify an index value starting at 1 when calling the getAccount function because NEAR starts with account index 1.
import { providers, transactions, utils } from 'near-api-js';
import { AccessKeyView } from 'near-api-js/lib/providers/provider';
import { Transaction } from 'near-api-js/lib/transaction';
import { Account, CHAIN } from '@dsrv/kms/lib/types';
import { Near } from '@dsrv/kms/lib/blockchains/near';
interface RawTransaction {
unSignedTx: Transaction;
serializedTx: string;
}
export const getNearTx = async (mnemonic: string): Promise<RawTransaction> => {
/* 1. get Account */
const account = Near.getAccount({
mnemonic,
path: { type: CHAIN.NEAR, account: 0, index: 1 },
});
/* 2. make raw transaction */
const provider = new providers.JsonRpcProvider({
url: 'https://rpc.testnet.near.org',
});
const helperURL = `https://near-utils.welldonestudio.io/accounts?address=${account.address}`;
const accountIds = await fetch(helperURL).then((res) => res.json());
const signerId = accountIds[Object.keys(accountIds).length - 1];
const { publicKey } = account;
const param = {
request_type: 'view_access_key',
finality: 'final',
account_id: signerId,
public_key: publicKey,
};
const accessKey = await provider.query<AccessKeyView>(param);
const actions = [transactions.transfer(new BN(10))];
const recentBlockHash = utils.serialize.base_decode(accessKey.block_hash);
const transaction = transactions.createTransaction(
accountIds[0],
utils.PublicKey.fromString(publicKey),
accountIds[0],
Number(accessKey.nonce) + 1,
actions,
recentBlockHash,
);
const bytes = transaction.encode();
return {
serializedTx: `0x${Buffer.from(bytes).toString('hex')}`,
unSignedTx: transaction,
};
};
2. getNearSignature
We then develop a method called getNearSignature
that produces a signature by using serializedTx as a factor in order to gain a signature for the transaction.
import { CHAIN } from '@dsrv/kms/lib/types';
import { Near } from '@dsrv/kms/lib/blockchains/near';
export const getNearSignature = (serializedTx: string): string => {
const { signature } = Near.signTx(
{
mnemonic,
path: { type: CHAIN.NEAR, account: 0, index: 1 },
},
serializedTx,
);
return signature;
};
3. createNearSignedTx
Finally, we develop the createNearSignedTx
function, which takes an unsignedTx
and a signature
generated earlier and returns a signed transaction.
import { Signature, SignedTransaction, Transaction } from 'near-api-js/lib/transaction';
interface createNearSignedTxProps {
unSignedTx: Transaction;
signature: string;
}
/* create singedTx by combining tx and signature */
export const createNearSignedTx = ({ unSignedTx, signature }: createNearSignedTxProps): string => {
const unSignedbytes = unSignedTx.encode();
const unSignedSerializedTx = Buffer.from(unSignedbytes).toString('base64');
const transaction = Transaction.decode(Buffer.from(unSignedSerializedTx, 'base64'));
const signedTx = new SignedTransaction({
transaction,
signature: new Signature({
keyType: transaction.publicKey.keyType,
data: Buffer.from(signature.replace('0x', ''), 'hex'),
}),
});
const bytes = signedTx.encode();
const serializedTx = Buffer.from(bytes).toString('base64');
return serializedTx;
};
Finally, you can construct a getNearSignedTx
function that returns a signed transaction by combining the functions you made before, getNearTx
, getNearSignature
, and createNearSignedTx
.
export const getNearSignedTx = async (mnemonic: string) => {
/* 1. get rawTransaction */
const { serializedTx, unSignedTx } = await getNearTx(mnemonic);
/* 2. get signature */
const nearSignature = getNearSignature(serializedTx);
/* 3. create singedTx by combining rawTransaction and signature */
const nearSignedTx = createNearSignedTx({
unSignedTx,
signature: nearSignature,
});
return nearSignedTx;
};
Send Signed transaction
You can transmit the transaction using a signed transaction you've prepared.
import { providers } from 'near-api-js';
export const sendNearTransaction = async (serializedTx: string) => {
const rpcUrl = 'https://rpc.testnet.near.org';
const provider = new providers.JsonRpcProvider({ url: rpcUrl });
const txResult = await provider.sendJsonRpc('broadcast_tx_commit', [serializedTx]);
return txResult;
};
const mnemonic = 'sample mnemonic';
const main = async () => {
const nearSignedTx = await getNearSignedTx(mnemonic);
const nearTxResult = await sendNearTransaction(nearSignedTx);
console.log('Near Tx Result : ', nearTxResult);
};
main();
Examples
To complete the transaction, follow the steps outlined below. A faucet is required to transmit a transaction. You can request faucet through the FAUCET tab in the wallet.
The loss of all cryptocurrency holdings is possible if mnemonic is revealed. To execute the following example, use a test or development mnemonic.