UNPKG

crypto-wallet-core

Version:

A multi-currency support library for address derivation, private key creation, and transaction creation

247 lines 13 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.SOLTxProvider = void 0; const SolComputeBudget = __importStar(require("@solana-program/compute-budget")); const SolComputeMemo = __importStar(require("@solana-program/memo")); const SolSystem = __importStar(require("@solana-program/system")); const SolKit = __importStar(require("@solana/kit")); class SOLTxProvider { MAX_TRANSFERS = 12; MINIMUM_PRIORITY_FEE = 1000; create(params) { const { recipients, from, nonce, nonceAddress, category, space, blockHash, blockHeight, priorityFee, txInstructions, computeUnits, memo } = params; const fromAddress = SolKit.address(from); let txType = ['0', 0].includes(params?.txType) ? 0 : 'legacy'; switch (category?.toLowerCase()) { case 'transfer': default: if (recipients.length > this.MAX_TRANSFERS) { throw new Error('Too many recipients'); } let transactionMessage = SolKit.pipe(SolKit.createTransactionMessage({ version: txType }), tx => SolKit.setTransactionMessageFeePayer(fromAddress, tx)); let lifetimeConstrainedTx; if (nonce) { const nonceAccountAddress = SolKit.address(nonceAddress); const nonceAuthorityAddress = fromAddress; lifetimeConstrainedTx = SolKit.setTransactionMessageLifetimeUsingDurableNonce({ nonce: nonce, nonceAccountAddress, nonceAuthorityAddress }, transactionMessage); } else { const recentBlockhash = { blockhash: blockHash, lastValidBlockHeight: BigInt(blockHeight) }; lifetimeConstrainedTx = SolKit.setTransactionMessageLifetimeUsingBlockhash(recentBlockhash, transactionMessage); } const transferInstructions = txInstructions || []; if (!transferInstructions.length) { for (const recipient of recipients) { const { address: recipientAddress, amount: recipientAmount } = recipient; transferInstructions.push(SolSystem.getTransferSolInstruction({ amount: BigInt(recipientAmount), destination: SolKit.address(recipientAddress), source: { address: fromAddress, signTransactions: async () => [] } })); } } if (priorityFee) { const maxPriorityFee = Math.max(this.MINIMUM_PRIORITY_FEE, priorityFee); transferInstructions.push(SolComputeBudget.getSetComputeUnitPriceInstruction({ microLamports: maxPriorityFee })); } if (computeUnits) { transferInstructions.push(SolComputeBudget.getSetComputeUnitLimitInstruction({ units: computeUnits })); } if (memo) { const memoInstruction = SolComputeMemo.getAddMemoInstruction({ memo }); transferInstructions.push(memoInstruction); } const transferTxMessage = SolKit.appendTransactionMessageInstructions(transferInstructions, lifetimeConstrainedTx); const compiledTx = SolKit.compileTransaction(transferTxMessage); return SolKit.getBase64EncodedWireTransaction(compiledTx); case 'createAccount': const { fromKeyPair } = params; const { amount, addressKeyPair } = recipients[0]; const _space = space || 200; const _amount = Number(amount); if (!addressKeyPair) { throw new Error('New address keypair is required to create an account.'); } const recentBlockhash = { blockhash: blockHash, lastValidBlockHeight: BigInt(blockHeight) }; const createAccountInstructions = []; createAccountInstructions.push(SolSystem.getCreateAccountInstruction({ payer: fromKeyPair, newAccount: addressKeyPair, lamports: _amount, space: _space, programAddress: SolSystem.SYSTEM_PROGRAM_ADDRESS })); const txMessage = SolKit.pipe(SolKit.createTransactionMessage({ version: txType }), (tx) => SolKit.setTransactionMessageFeePayerSigner(fromKeyPair, tx)); lifetimeConstrainedTx = SolKit.setTransactionMessageLifetimeUsingBlockhash(recentBlockhash, txMessage); if (priorityFee) { const maxPriorityFee = Math.max(this.MINIMUM_PRIORITY_FEE, priorityFee); createAccountInstructions.push(SolComputeBudget.getSetComputeUnitPriceInstruction({ microLamports: maxPriorityFee })); } if (computeUnits) { createAccountInstructions.push(SolComputeBudget.getSetComputeUnitLimitInstruction({ units: computeUnits })); } const completeMessage = SolKit.appendTransactionMessageInstructions(createAccountInstructions, lifetimeConstrainedTx); const compiled = SolKit.compileTransaction(completeMessage); return SolKit.getBase64EncodedWireTransaction(compiled); } } decodeRawTransaction({ rawTx, decodeTransactionMessage = true }) { if (typeof rawTx !== 'string') { throw new Error(`Raw transaction expected to be a string. Found ${typeof rawTx} instead.`); } const uint8ArrayTx = SolKit.getBase64Encoder().encode(rawTx); const decodedTx = SolKit.getTransactionDecoder().decode(uint8ArrayTx); if (decodeTransactionMessage) { const decompiledTransactionMessage = this.decodeTransactionMessage(decodedTx?.messageBytes); decodedTx.lifetimeConstraint = decompiledTransactionMessage.lifetimeConstraint; } return decodedTx; } decodeTransactionMessage(bytes) { const compiledTransactionMessage = SolKit.getCompiledTransactionMessageDecoder().decode(bytes); return SolKit.decompileTransactionMessage(compiledTransactionMessage); } async sign(params) { const { tx, key } = params; const decodedTx = this.decodeRawTransaction({ rawTx: tx, decodeTransactionMessage: false }); const privKeyBytes = SolKit.getBase58Encoder().encode(key.privKey); const keypair = await SolKit.createKeyPairFromPrivateKeyBytes(privKeyBytes); const signedTransaciton = await SolKit.signTransaction([keypair], decodedTx); return SolKit.getBase64EncodedWireTransaction(signedTransaciton); } async signPartially(params) { const { tx, key } = params; const decodedTx = this.decodeRawTransaction({ rawTx: tx, decodeTransactionMessage: false }); const privKeyBytes = SolKit.getBase58Encoder().encode(key.privKey); const keypair = await SolKit.createKeyPairFromPrivateKeyBytes(privKeyBytes); const signedTransaciton = await SolKit.partiallySignTransaction([keypair], decodedTx); return SolKit.getBase64EncodedWireTransaction(signedTransaciton); } async signMessage(params) { const { key, messageBytes } = params; const privKeyBytes = SolKit.getBase58Encoder().encode(key.privKey); const keypair = await SolKit.createKeyPairFromPrivateKeyBytes(privKeyBytes); const signedBytes = await SolKit.signBytes(keypair.privateKey, messageBytes); return SolKit.getBase58Decoder().decode(signedBytes); } async getSignature(params) { const { tx, keys } = params; const key = keys[0]; const signedTx = await this.sign({ tx, key }); const decodedTx = this.decodeRawTransaction({ rawTx: signedTx, decodeTransactionMessage: false }); const sigEncoding = decodedTx.signatures[key.address]; return SolKit.getBase58Decoder().decode(sigEncoding); } applySignature(params) { const { tx, signature } = params; const signatures = [SolKit.getBase58Encoder().encode(signature)]; const transaction = SolKit.getBase64Encoder().encode(tx); const transformWithNewSignatures = (_tx) => { const { messageBytes } = _tx; const signerAddressesDecoder = SolKit.getTupleDecoder([ SolKit.getTransactionVersionDecoder(), SolKit.padRightDecoder(SolKit.getU8Decoder(), 2), SolKit.getArrayDecoder(SolKit.getAddressDecoder(), { size: SolKit.getShortU16Decoder() }) ]); const [, numRequiredSignatures, staticAddresses] = signerAddressesDecoder.decode(messageBytes); const signerAddresses = staticAddresses.slice(0, numRequiredSignatures); if (signerAddresses.length !== signatures.length) { throw new Error(`The transaction message expected the transaction to have ${signerAddresses.length} signatures, got ${signatures.length}.`); } const signaturesMap = {}; for (let index = 0; index < signerAddresses.length; index++) { const address = signerAddresses[index]; const signatureForAddress = signatures[index]; if (signatureForAddress.every((b) => b === 0)) { signaturesMap[address] = null; } else { signaturesMap[address] = signatureForAddress; } } return { messageBytes, signatures: Object.freeze(signaturesMap) }; }; const decoderTransform = SolKit.transformDecoder(SolKit.getStructDecoder([ ['signatures', SolKit.getArrayDecoder(SolKit.fixDecoderSize(SolKit.getBytesDecoder(), 64), { size: SolKit.getShortU16Decoder() })], ['messageBytes', SolKit.getBytesDecoder()] ]), transformWithNewSignatures); const signedTx = decoderTransform.decode(transaction); return SolKit.getBase64EncodedWireTransaction(signedTx); } getHash(params) { const { tx } = params; const decodedTx = this.decodeRawTransaction({ rawTx: tx, decodeTransactionMessage: false }); const pubKeys = Object.keys(decodedTx.signatures); let signature; if (pubKeys.length == 1) { signature = decodedTx.signatures[pubKeys[0]]; } else if (pubKeys.length > 1) { try { const compiledTransactionMessage = SolKit.getCompiledTransactionMessageDecoder().decode(decodedTx.messageBytes); const feePayerAddress = compiledTransactionMessage.staticAccounts[0]; signature = decodedTx.signatures[feePayerAddress]; } catch (err) { throw new Error('unable to get fee payer signature %o', err.stack || err.message || err); } } if (!signature) { throw new Error('tx is unsigned by fee payer'); } return SolKit.getBase58Decoder().decode(signature); } } exports.SOLTxProvider = SOLTxProvider; //# sourceMappingURL=index.js.map