UNPKG

@tatumio/tatum-v1

Version:

Tatum API client allows browsers and Node.js clients to interact with Tatum API.

419 lines 45 kB
"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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