crypto-wallet-core
Version:
A multi-currency support library for address derivation, private key creation, and transaction creation
247 lines • 13 kB
JavaScript
;
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