@tatumio/tatum-v1
Version:
Tatum API client allows browsers and Node.js clients to interact with Tatum API.
419 lines • 45 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.flowSendTransaction = exports.flowSendCustomTransaction = exports.sendFlowNftBurnToken = exports.sendFlowNftTransferToken = exports.sendFlowNftMintMultipleToken = exports.sendFlowNftMintToken = exports.getFlowNftTokenByAddress = exports.getFlowNftMetadata = exports.flowAddPublicKeyToAccount = exports.flowCreateAccountFromPublicKey = exports.flowSignKMSTransaction = exports.getFlowApiSigner = exports.getFlowSigner = exports.flowSign = exports.FlowTxType = void 0;
// @ts-ignore
const fcl = __importStar(require("@onflow/fcl"));
// @ts-ignore
const types = __importStar(require("@onflow/types"));
// @ts-ignore
const util_encode_key_1 = require("@onflow/util-encode-key");
const elliptic = __importStar(require("elliptic"));
const sha3_1 = require("sha3");
const blockchain_1 = require("../blockchain");
const tatum_1 = require("../connector/tatum");
const constants_1 = require("../constants");
const model_1 = require("../model");
const wallet_1 = require("../wallet");
const flowTransaction_1 = require("./flowTransaction");
var FlowTxType;
(function (FlowTxType) {
FlowTxType[FlowTxType["CREATE_ACCOUNT"] = 0] = "CREATE_ACCOUNT";
FlowTxType[FlowTxType["ADD_PK_TO_ACCOUNT"] = 1] = "ADD_PK_TO_ACCOUNT";
FlowTxType[FlowTxType["TRANSFER"] = 2] = "TRANSFER";
FlowTxType[FlowTxType["DEPLOY_NFT"] = 3] = "DEPLOY_NFT";
FlowTxType[FlowTxType["MINT_NFT"] = 4] = "MINT_NFT";
FlowTxType[FlowTxType["MINT_MULTIPLE_NFT"] = 5] = "MINT_MULTIPLE_NFT";
FlowTxType[FlowTxType["BURN_NFT"] = 6] = "BURN_NFT";
FlowTxType[FlowTxType["TRANSFER_NFT"] = 7] = "TRANSFER_NFT";
FlowTxType[FlowTxType["CUSTOM_TX"] = 8] = "CUSTOM_TX";
})(FlowTxType = exports.FlowTxType || (exports.FlowTxType = {}));
const flowSign = (pk, msg) => {
const keyPair = new elliptic.ec('secp256k1').keyFromPrivate(pk);
const signature = keyPair.sign(new sha3_1.SHA3(256).update(msg).digest());
const r = signature.r.toArrayLike(Buffer, 'be', 32);
const s = signature.s.toArrayLike(Buffer, 'be', 32);
return Buffer.concat([r, s]).toString('hex');
};
exports.flowSign = flowSign;
const getFlowSigner = (pk, address, keyId = 0) => {
return {
signer: (account) => {
return Object.assign(Object.assign({}, account), { tempId: `${address}-${keyId}`, addr: fcl.sansPrefix(address), keyId: Number(keyId), signingFunction: async (data) => {
return {
addr: fcl.withPrefix(address),
keyId: Number(keyId),
signature: exports.flowSign(pk, Buffer.from(data.message, 'hex')),
};
} });
}
};
};
exports.getFlowSigner = getFlowSigner;
const getFlowApiSigner = (isPayer) => {
const keyHash = Date.now();
const signer = async (account) => {
const { address, keyId } = await blockchain_1.flowGetSignKey(isPayer);
if (!isPayer) {
process.env[`FLOW_PROPOSAL_KEY_${keyHash}`] = `${keyId}`;
}
return Object.assign(Object.assign({}, account), { tempId: `${address}-${keyId}`, addr: fcl.sansPrefix(address), keyId, signingFunction: async (data) => {
return {
addr: fcl.withPrefix(address),
keyId: Number(keyId),
signature: (await blockchain_1.flowSignWithKey(data.message, isPayer)).signature,
};
} });
};
return { signer, keyHash: `FLOW_PROPOSAL_KEY_${keyHash}` };
};
exports.getFlowApiSigner = getFlowApiSigner;
const sendTransaction = async (testnet, { code, args, proposer, authorizations, payer, keyHash, }) => {
fcl.config().put('accessNode.api', testnet ? 'https://rest-testnet.onflow.org' : 'https://rest-mainnet.onflow.org');
let response;
try {
response = await fcl.send([
fcl.transaction(code),
fcl.args(args.map(arg => fcl.arg(arg.type === 'UInt64' ? parseInt(arg.value) : arg.value, arg.type === 'Array' ? types[arg.type](types[arg.subType]) : types[arg.type]))),
fcl.proposer(proposer),
fcl.authorizations(authorizations),
fcl.payer(payer),
fcl.limit(9999),
]);
}
catch (e) {
try {
if (keyHash) {
await blockchain_1.flowBroadcastTx('', undefined, keyHash ? parseInt((process.env[keyHash] || '0')) : undefined);
delete process.env[keyHash];
}
// eslint-disable-next-line no-empty
}
catch (_) {
}
throw e;
}
const { transactionId } = response;
try {
const { error, events } = await fcl.tx(response).onceSealed();
return {
id: transactionId,
error,
events,
};
}
finally {
try {
if (keyHash) {
await blockchain_1.flowBroadcastTx(transactionId, undefined, keyHash ? parseInt((process.env[keyHash] || '0')) : undefined);
delete process.env[keyHash];
}
// eslint-disable-next-line no-empty
}
catch (_) {
}
}
};
const sendScript = async (testnet, code, args) => {
fcl.config().put('accessNode.api', testnet ? 'https://rest-testnet.onflow.org' : 'https://rest-mainnet.onflow.org');
const response = await fcl.send([
fcl.script(code),
fcl.args(args.map(arg => fcl.arg(arg.type === 'UInt64' ? parseInt(arg.value) : arg.value, types[arg.type]))),
]);
return fcl.decode(response);
};
const flowSignKMSTransaction = async (tx, privateKeys, testnet) => {
if (tx.chain !== model_1.Currency.FLOW) {
throw Error('Unsupported chain.');
}
const { type, body } = JSON.parse(tx.serializedTransaction);
switch (type) {
case FlowTxType.CREATE_ACCOUNT:
return await exports.flowCreateAccountFromPublicKey(testnet, body.publicKey, body.account, privateKeys[0]);
case FlowTxType.ADD_PK_TO_ACCOUNT:
return await exports.flowAddPublicKeyToAccount(testnet, body.publicKey, body.account, privateKeys[0]);
case FlowTxType.TRANSFER:
return await exports.flowSendTransaction(testnet, Object.assign(Object.assign({}, body), { privateKey: privateKeys[0] }));
case FlowTxType.TRANSFER_NFT:
return await exports.sendFlowNftTransferToken(testnet, Object.assign(Object.assign({}, body), { privateKey: privateKeys[0] }));
case FlowTxType.MINT_NFT:
return await exports.sendFlowNftMintToken(testnet, Object.assign(Object.assign({}, body), { privateKey: privateKeys[0] }));
case FlowTxType.MINT_MULTIPLE_NFT:
return await exports.sendFlowNftMintMultipleToken(testnet, Object.assign(Object.assign({}, body), { privateKey: privateKeys[0] }));
case FlowTxType.BURN_NFT:
return await exports.sendFlowNftBurnToken(testnet, Object.assign(Object.assign({}, body), { privateKey: privateKeys[0] }));
default:
return await exports.flowSendCustomTransaction(testnet, Object.assign(Object.assign({}, body), { privateKey: privateKeys[0] }));
}
};
exports.flowSignKMSTransaction = flowSignKMSTransaction;
/**
* Create account on the FLOW network. It automatically creates 100 0-weight proposal keys, which are managed by Tatum API - index 1-100.
* Main 1000 weight authorizer key is stored as a first one on index 0.
* @param testnet if we use testnet or not
* @param publicKey public key to assign to address as authorizer (1000 weight) key
* @param signerAddress address of the authorizer creator of the address on the chain
* @param signerPrivateKey private key of the authorizer creator of the address on the chain
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
*/
const flowCreateAccountFromPublicKey = async (testnet, publicKey, signerAddress, signerPrivateKey, proposer, payer) => {
var _a;
const code = flowTransaction_1.prepareCreateAccountWithFUSDFromPublicKeyTxTemplate(testnet);
const encodedPublicKey = util_encode_key_1.encodeKey(publicKey, util_encode_key_1.ECDSA_secp256k1, util_encode_key_1.SHA3_256, 1000);
const args = [{ type: 'String', value: encodedPublicKey }];
const auth = exports.getFlowSigner(signerPrivateKey, signerAddress).signer;
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const result = await sendTransaction(testnet, {
code, args,
proposer: proposer ? proposer(false) : proposalSigner,
authorizations: [auth],
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer,
keyHash,
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id, address: (_a = result.events.find((e) => e.type === 'flow.AccountCreated')) === null || _a === void 0 ? void 0 : _a.data.address };
};
exports.flowCreateAccountFromPublicKey = flowCreateAccountFromPublicKey;
/**
* Add public key to existing blockchain address with defined weight
* @param testnet
* @param publicKey key to add
* @param signerAddress address of the authorizer key
* @param signerPrivateKey key of the authorize key
* @param weight defaults to 1000 - weight of the key
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
*/
const flowAddPublicKeyToAccount = async (testnet, publicKey, signerAddress, signerPrivateKey, weight = 0, proposer, payer) => {
const code = flowTransaction_1.prepareAddPublicKeyToAccountTxTemplate();
const encodedPublicKey = util_encode_key_1.encodeKey(publicKey, util_encode_key_1.ECDSA_secp256k1, util_encode_key_1.SHA3_256, weight);
const args = [{ type: 'String', value: encodedPublicKey }];
const auth = exports.getFlowSigner(signerPrivateKey, signerAddress).signer;
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const result = await sendTransaction(testnet, {
code, args,
proposer: proposer ? proposer(false) : proposalSigner,
authorizations: [auth],
keyHash,
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer,
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id, address: result.events[0].data.address };
};
exports.flowAddPublicKeyToAccount = flowAddPublicKeyToAccount;
const getFlowNftMetadata = async (testnet, account, id, tokenType) => {
const code = flowTransaction_1.metadataFlowNftTokenScript(testnet);
const args = [{ type: 'Address', value: account }, { type: 'UInt64', value: id }, { type: 'String', value: tokenType }];
return await sendScript(testnet, code, args);
};
exports.getFlowNftMetadata = getFlowNftMetadata;
const getFlowNftTokenByAddress = async (testnet, account, tokenType) => {
const code = flowTransaction_1.tokenByAddressFlowNftTokenScript(testnet);
const args = [{ type: 'Address', value: account }, { type: 'String', value: tokenType }];
return await sendScript(testnet, code, args);
};
exports.getFlowNftTokenByAddress = getFlowNftTokenByAddress;
/**
* Send Flow NFT mint token transaction to the blockchain. This method broadcasts signed transaction to the blockchain.
* This operation is irreversible.
* @param testnet
* @param body content of the transaction to broadcast
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
* @returns txId id of the transaction in the blockchain
*/
const sendFlowNftMintToken = async (testnet, body, proposer, payer) => {
var _a;
await tatum_1.validateBody(body, model_1.FlowMintNft);
const code = flowTransaction_1.mintFlowNftTokenTxTemplate(testnet);
const { url, contractAddress: tokenType, to, mnemonic, index, account, privateKey } = body;
const args = [{ type: 'Address', value: to }, { type: 'String', value: url }, { type: 'String', value: tokenType }];
const pk = (mnemonic && index && index >= 0) ? await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.FLOW, testnet, mnemonic, index) : privateKey;
const auth = exports.getFlowSigner(pk, account).signer;
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const result = await sendTransaction(testnet, {
code, args,
proposer: proposer ? proposer(false) : proposalSigner,
authorizations: [auth],
keyHash,
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer,
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id, tokenId: `${(_a = result.events.find((e) => e.type.includes('TatumMultiNFT.Minted'))) === null || _a === void 0 ? void 0 : _a.data.id}` };
};
exports.sendFlowNftMintToken = sendFlowNftMintToken;
/**
* Send Flow NFT mint multiple tokens transaction to the blockchain. This method broadcasts signed transaction to the blockchain.
* This operation is irreversible.
* @param testnet
* @param body content of the transaction to broadcast
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
* @returns txId id of the transaction in the blockchain
*/
const sendFlowNftMintMultipleToken = async (testnet, body, proposer, payer) => {
await tatum_1.validateBody(body, model_1.FlowMintMultipleNft);
const code = flowTransaction_1.mintFlowMultipleNftTokenTxTemplate(testnet);
const { url, contractAddress: tokenType, to, mnemonic, index, account, privateKey } = body;
const args = [{ type: 'Array', subType: 'Address', value: to }, { type: 'Array', subType: 'String', value: url }, { type: 'String', value: tokenType }];
const pk = (mnemonic && index && index >= 0) ? await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.FLOW, testnet, mnemonic, index) : privateKey;
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const auth = exports.getFlowSigner(pk, account).signer;
const result = await sendTransaction(testnet, {
code, args, proposer: proposer ? proposer(false) : proposalSigner, authorizations: [auth],
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer,
keyHash,
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id, tokenId: result.events.filter((e) => e.type.includes('TatumMultiNFT.Minted')).map(e => e.data.id) };
};
exports.sendFlowNftMintMultipleToken = sendFlowNftMintMultipleToken;
/**
* Send Flow NFT transfer token transaction to the blockchain. This method broadcasts signed transaction to the blockchain.
* This operation is irreversible.
* @param testnet
* @param body content of the transaction to broadcast
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
* @returns {txId: string, events: any[]} id of the transaction in the blockchain and events this tx produced
*/
const sendFlowNftTransferToken = async (testnet, body, proposer, payer) => {
await tatum_1.validateBody(body, model_1.FlowTransferNft);
const code = flowTransaction_1.transferFlowNftTokenTxTemplate(testnet);
const { tokenId, to, mnemonic, index, account, privateKey } = body;
const args = [{ type: 'Address', value: to }, { type: 'UInt64', value: tokenId }];
const pk = (mnemonic && index && index >= 0) ? await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.FLOW, testnet, mnemonic, index) : privateKey;
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const auth = exports.getFlowSigner(pk, account).signer;
const result = await sendTransaction(testnet, {
code, args, proposer: proposer ? proposer(false) : proposalSigner, authorizations: [auth],
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer,
keyHash,
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id };
};
exports.sendFlowNftTransferToken = sendFlowNftTransferToken;
/**
* Send Flow NFT burn token transaction to the blockchain. This method broadcasts signed transaction to the blockchain.
* This operation is irreversible.
* @param testnet
* @param body content of the transaction to broadcast
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
* @returns txId id of the transaction in the blockchain
*/
const sendFlowNftBurnToken = async (testnet, body, proposer, payer) => {
await tatum_1.validateBody(body, model_1.FlowBurnNft);
const code = flowTransaction_1.burnFlowNftTokenTxTemplate(testnet);
const { tokenId, contractAddress: tokenType, mnemonic, index, account, privateKey } = body;
const args = [{ type: 'UInt64', value: tokenId }, { type: 'String', value: tokenType }];
const pk = (mnemonic && index && index >= 0) ? await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.FLOW, testnet, mnemonic, index) : privateKey;
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const auth = exports.getFlowSigner(pk, account).signer;
const result = await sendTransaction(testnet, {
code, args, proposer: proposer ? proposer(false) : proposalSigner, authorizations: [auth],
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer,
keyHash,
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id };
};
exports.sendFlowNftBurnToken = sendFlowNftBurnToken;
/**
* Send custom transaction to the FLOW network
* @param testnet
* @param body content of the transaction to broadcast
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
* @returns txId id of the transaction in the blockchain
*/
const flowSendCustomTransaction = async (testnet, body, proposer, payer) => {
await tatum_1.validateBody(body, model_1.TransferFlowCustomTx);
const pk = body.privateKey || await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.FLOW, testnet, body.mnemonic, body.index);
const auth = exports.getFlowSigner(pk, body.account).signer;
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const result = await sendTransaction(testnet, {
code: body.transaction, args: body.args,
proposer: proposer ? proposer(false) : proposalSigner,
authorizations: [auth],
keyHash,
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id, events: result.events };
};
exports.flowSendCustomTransaction = flowSendCustomTransaction;
/**
* Send FLOW or FUSD from account to account.
* @param testnet
* @param body content of the transaction to broadcast
* @param proposer function to obtain proposer key from
* @param payer function to obtain payer key from
* @returns txId id of the transaction in the blockchain
*/
const flowSendTransaction = async (testnet, body, proposer, payer) => {
await tatum_1.validateBody(body, model_1.TransferFlow);
let tokenAddress;
let tokenName;
let tokenStorage;
if (body.currency === model_1.Currency.FLOW) {
tokenAddress = testnet ? constants_1.FLOW_TESTNET_ADDRESSES.FlowToken : constants_1.FLOW_MAINNET_ADDRESSES.FlowToken;
tokenName = 'FlowToken';
tokenStorage = 'flowToken';
}
else {
tokenAddress = testnet ? constants_1.FLOW_TESTNET_ADDRESSES.FUSD : constants_1.FLOW_MAINNET_ADDRESSES.FUSD;
tokenName = 'FUSD';
tokenStorage = 'fusd';
}
const code = flowTransaction_1.prepareTransferFlowTxTemplate(testnet, tokenAddress, tokenName, tokenStorage);
const args = [{ value: parseFloat(body.amount).toFixed(8), type: 'UFix64' }, { value: body.to, type: 'Address' }];
const pk = body.privateKey || await wallet_1.generatePrivateKeyFromMnemonic(model_1.Currency.FLOW, testnet, body.mnemonic, body.index);
const { signer: proposalSigner, keyHash } = proposer ? proposer(false) : exports.getFlowApiSigner(false);
const auth = exports.getFlowSigner(pk, body.account).signer;
const result = await sendTransaction(testnet, {
code, args, proposer: proposer ? proposer(false) : proposalSigner, authorizations: [auth],
payer: payer ? payer(true) : exports.getFlowApiSigner(true).signer,
keyHash,
});
if (result.error) {
throw new Error(result.error);
}
return { txId: result.id };
};
exports.flowSendTransaction = flowSendTransaction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvdy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmFuc2FjdGlvbi9mbG93LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxhQUFhO0FBQ2IsaURBQW1DO0FBQ25DLGFBQWE7QUFDYixxREFBdUM7QUFDdkMsYUFBYTtBQUNiLDZEQUE4RTtBQUM5RSxtREFBcUM7QUFDckMsK0JBQTBCO0FBQzFCLDhDQUErRTtBQUMvRSw4Q0FBZ0Q7QUFDaEQsNENBQTRFO0FBQzVFLG9DQUFnSztBQUNoSyxzQ0FBeUQ7QUFDekQsdURBVTJCO0FBRTNCLElBQVksVUFVWDtBQVZELFdBQVksVUFBVTtJQUNsQiwrREFBYyxDQUFBO0lBQ2QscUVBQWlCLENBQUE7SUFDakIsbURBQVEsQ0FBQTtJQUNSLHVEQUFVLENBQUE7SUFDVixtREFBUSxDQUFBO0lBQ1IscUVBQWlCLENBQUE7SUFDakIsbURBQVEsQ0FBQTtJQUNSLDJEQUFZLENBQUE7SUFDWixxREFBUyxDQUFBO0FBQ2IsQ0FBQyxFQVZXLFVBQVUsR0FBVixrQkFBVSxLQUFWLGtCQUFVLFFBVXJCO0FBdUNNLE1BQU0sUUFBUSxHQUFHLENBQUMsRUFBVSxFQUFFLEdBQVcsRUFBRSxFQUFFO0lBQ2hELE1BQU0sT0FBTyxHQUFHLElBQUksUUFBUSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDaEUsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLFdBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNuRSxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FDN0IsTUFBTSxFQUNOLElBQUksRUFDSixFQUFFLENBQ0wsQ0FBQztJQUNGLE1BQU0sQ0FBQyxHQUFHLFNB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