@coolwallet/sol
Version:
Coolwallet Solana sdk
712 lines (648 loc) • 26.5 kB
text/typescript
import crypto from 'node:crypto';
import { inspect } from 'node:util';
import * as bip39 from 'bip39';
import base58 from 'bs58';
import { Transport } from '@coolwallet/core';
import { createTransport } from '@coolwallet/transport-jre-http';
import { initialize, getTxDetail, DisplayBuilder, CURVE, HDWallet } from '@coolwallet/testing-library';
import { Keypair, Transaction, SystemProgram, PublicKey, StakeProgram, LAMPORTS_PER_SOL } from '@solana/web3.js';
import { createAssociatedTokenAccountInstruction, createTransferInstruction } from '@solana/spl-token';
import SOL, { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../src';
import * as stringUtil from '../src/utils/stringUtil';
import { TOKEN_INFO } from '../src/config/tokenInfos';
type PromiseValue<T> = T extends Promise<infer V> ? V : never;
const sol = new SOL();
const mnemonic = bip39.generateMnemonic();
function omit<T extends Record<string, any>>(obj: T, key: keyof T) {
return Object.keys(obj).reduce((o, k) => {
if (k === key) return o;
return {
...o,
[k]: obj[k],
};
}, {} as T);
}
describe('Test Solana SDK', () => {
const tokens = Object.values(TOKEN_INFO);
const getRandInt = (max: number) => Math.floor(Math.random() * max);
const getRandToken = () => omit(tokens[getRandInt(tokens.length)], 'signature');
const getRandWallet = () => stringUtil.pubKeyToAddress(crypto.randomBytes(32).toString('hex'));
let props: PromiseValue<ReturnType<typeof initialize>>;
let transport: Transport;
let walletAddress = '';
const wallet = new HDWallet(CURVE.ED25519);
const bip32Path = (addressIndex: number) => `m/44'/501'/${addressIndex}'/0'`;
beforeAll(async () => {
transport = (await createTransport())!;
props = await initialize(transport, mnemonic);
const address = await sol.getAddress(transport, props.appPrivateKey, props.appId, 0);
walletAddress = address;
await wallet.setMnemonic(mnemonic);
});
it('Test Get Address', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expected = Keypair.fromSeed(node.privateKey);
const publicKey = await node.getPublicKey();
expect(walletAddress).toEqual(stringUtil.pubKeyToAddress(publicKey?.toString('hex') ?? ''));
expect(walletAddress).toEqual(expected.publicKey.toString());
expect(sol.isValidPublicKey(publicKey ?? '')).toBeTruthy();
const token = getRandWallet();
const [token_account] = sol.findProgramAddress(
[publicKey!, TOKEN_PROGRAM_ID, base58.decode(token)],
ASSOCIATED_TOKEN_PROGRAM_ID
);
expect(sol.isValidPublicKey(token_account)).toBeFalsy();
});
it('Test Get Token Address', async () => {
const fromPubkey = getRandWallet();
const token = getRandWallet();
const [result] = sol.findProgramAddress(
[base58.decode(fromPubkey), TOKEN_PROGRAM_ID, base58.decode(token)],
ASSOCIATED_TOKEN_PROGRAM_ID
);
const [expected] = PublicKey.findProgramAddressSync(
[base58.decode(fromPubkey), TOKEN_PROGRAM_ID, base58.decode(token)],
new PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID)
);
expect(result).toEqual(expected.toString());
});
it('Test Normal Transfer', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const toPubkey = getRandWallet();
const recentBlockhash = getRandWallet();
const lamports = ((getRandInt(10000000) + 1) / 10000000.0) * LAMPORTS_PER_SOL;
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
toPubkey,
recentBlockhash,
lamports,
},
addressIndex: 0,
};
const signedTx = await sol.signTransferTransaction(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = new Transaction({
feePayer: expectedWallet.publicKey,
recentBlockhash,
}).add(
SystemProgram.transfer({
fromPubkey: expectedWallet.publicKey,
toPubkey: new PublicKey(toPubkey),
lamports,
})
);
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Normal Transfer params', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.addressPage(toPubkey)
.amountPage(+lamports / LAMPORTS_PER_SOL)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Create Associate Account', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const associateAccount = getRandWallet();
const token = getRandToken();
const recentBlockhash = getRandWallet();
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
owner: walletAddress,
associateAccount,
recentBlockhash,
token: token.address,
},
addressIndex: 0,
};
const signedTx = await sol.signAssociateTokenAccount(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = new Transaction({
feePayer: expectedWallet.publicKey,
recentBlockhash,
});
const instruction = createAssociatedTokenAccountInstruction(
expectedWallet.publicKey,
new PublicKey(associateAccount),
new PublicKey(expectedWallet.publicKey),
new PublicKey(token.address)
);
expectedTransaction.instructions = [instruction];
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Create Associate Account params', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.wrapPage('ToKEN', 'ACCoUNT')
.addressPage(associateAccount)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test SPL Token Transaction', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const fromTokenAccount = getRandWallet();
const toTokenAccount = getRandWallet();
const recentBlockhash = getRandWallet();
const tokenInfo = getRandToken();
const amount = getRandInt(10 * 10 ** tokenInfo.decimals) + 1;
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
walletAddress,
fromTokenAccount,
toTokenAccount,
recentBlockhash,
amount,
tokenInfo,
},
addressIndex: 0,
};
const signedTx = await sol.signTransferSplTokenTransaction(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = new Transaction({
feePayer: expectedWallet.publicKey,
recentBlockhash,
});
const instruction = createTransferInstruction(
new PublicKey(fromTokenAccount),
new PublicKey(toTokenAccount),
new PublicKey(walletAddress),
amount
);
expectedTransaction.instructions = [instruction];
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test SPL Token Transaction params', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.messagePage(tokenInfo.symbol)
.addressPage(toTokenAccount)
.amountPage(amount / 10 ** tokenInfo.decimals)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Create Token Account and SPL Token Transfer', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const FROM_PUBKEY = await node.getPublicKey();
const TO_PUBKEY = getRandWallet();
const tokenInfo = getRandToken();
const [fromTokenAccount] = sol.findProgramAddress(
[FROM_PUBKEY!, TOKEN_PROGRAM_ID, base58.decode(tokenInfo.address)],
ASSOCIATED_TOKEN_PROGRAM_ID
);
const [toTokenAccount] = sol.findProgramAddress(
[base58.decode(TO_PUBKEY), TOKEN_PROGRAM_ID, base58.decode(tokenInfo.address)],
ASSOCIATED_TOKEN_PROGRAM_ID
);
const recentBlockhash = getRandWallet();
const amount = getRandInt(10 * 10 ** tokenInfo.decimals) + 1;
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
fromTokenAccount,
toPubkey: TO_PUBKEY,
toTokenAccount,
recentBlockhash,
amount,
tokenInfo,
},
addressIndex: 0,
};
const signedTx = await sol.signCreateAndTransferSPLToken(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = new Transaction({
feePayer: expectedWallet.publicKey,
recentBlockhash,
})
.add(
createAssociatedTokenAccountInstruction(
new PublicKey(FROM_PUBKEY!),
new PublicKey(toTokenAccount),
new PublicKey(TO_PUBKEY),
new PublicKey(tokenInfo.address),
new PublicKey(TOKEN_PROGRAM_ID),
new PublicKey(ASSOCIATED_TOKEN_PROGRAM_ID)
)
)
.add(
createTransferInstruction(
new PublicKey(fromTokenAccount),
new PublicKey(toTokenAccount),
new PublicKey(FROM_PUBKEY!),
amount
)
);
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error(
'Expected Transaction:',
inspect(expectedTransaction.compileMessage(), {
showHidden: false,
depth: null,
colors: true,
})
);
console.error(
'Result Transaction:',
inspect(recoveredTx.compileMessage(), {
showHidden: false,
depth: null,
colors: true,
})
);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.messagePage(tokenInfo.symbol)
.addressPage(TO_PUBKEY)
.amountPage(amount / 10 ** tokenInfo.decimals)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Delegate', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const FROM_PUBKEY = expectedWallet.publicKey;
const recentBlockhash = getRandWallet();
const SEED = 'stake:0';
const STAKE_ACCOUNT = await sol.createWithSeed(FROM_PUBKEY.toBuffer(), SEED, StakeProgram.programId.toBuffer());
const VALIDATOR = new PublicKey(getRandWallet());
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
authorizedPubkey: FROM_PUBKEY.toString(),
stakePubkey: STAKE_ACCOUNT.toString(),
votePubkey: VALIDATOR.toString(),
recentBlockhash,
},
addressIndex: 0,
};
const signedTx = await sol.signDelegate(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = StakeProgram.delegate({
stakePubkey: new PublicKey(STAKE_ACCOUNT),
authorizedPubkey: FROM_PUBKEY,
votePubkey: VALIDATOR,
});
expectedTransaction.feePayer = FROM_PUBKEY;
expectedTransaction.recentBlockhash = recentBlockhash;
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(FROM_PUBKEY, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Delegate', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.messagePage('STAKE')
.addressPage(VALIDATOR.toBase58())
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Undelegate', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const FROM_PUBKEY = expectedWallet.publicKey;
const recentBlockhash = getRandWallet();
const SEED = 'stake:0';
const STAKE_ACCOUNT = await sol.createWithSeed(FROM_PUBKEY.toString(), SEED, StakeProgram.programId.toString());
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
stakePubkey: STAKE_ACCOUNT.toString(),
authorizedPubkey: walletAddress,
recentBlockhash,
},
addressIndex: 0,
};
const signedTx = await sol.signUndelegate(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = new Transaction({
feePayer: expectedWallet.publicKey,
recentBlockhash,
}).add(
StakeProgram.deactivate({
authorizedPubkey: new PublicKey(walletAddress),
stakePubkey: new PublicKey(STAKE_ACCOUNT),
})
);
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Undelegate params', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.messagePage('UnDel')
.addressPage(walletAddress)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Delegate And CreateAccountWithSeed', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const FROM_PUBKEY = expectedWallet.publicKey;
const recentBlockhash = getRandWallet();
const SEED = 'stake:0';
const STAKE_ACCOUNT = await sol.createWithSeed(FROM_PUBKEY.toString(), SEED, StakeProgram.programId.toString());
const VALIDATOR = new PublicKey(getRandWallet());
const lamports = ((getRandInt(10000000) + 1) / 10000000.0) * LAMPORTS_PER_SOL;
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
newAccountPubkey: STAKE_ACCOUNT,
basePubkey: walletAddress,
seed: SEED,
votePubkey: VALIDATOR.toString(),
lamports,
recentBlockhash,
},
addressIndex: 0,
};
const signedTx = await sol.signDelegateAndCreateAccountWithSeed(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = StakeProgram.createAccountWithSeed({
fromPubkey: FROM_PUBKEY,
stakePubkey: new PublicKey(STAKE_ACCOUNT),
basePubkey: FROM_PUBKEY,
seed: SEED,
authorized: {
staker: FROM_PUBKEY,
withdrawer: FROM_PUBKEY,
},
lamports,
});
expectedTransaction.feePayer = FROM_PUBKEY;
expectedTransaction.recentBlockhash = recentBlockhash;
const [delegateInstruction] = StakeProgram.delegate({
stakePubkey: new PublicKey(STAKE_ACCOUNT),
authorizedPubkey: FROM_PUBKEY,
votePubkey: VALIDATOR,
}).instructions;
expectedTransaction.add(delegateInstruction);
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(FROM_PUBKEY, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Delegate And CreateAccountWithSeed', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.messagePage('STAKE')
.addressPage(VALIDATOR.toBase58())
.amountPage(+lamports / LAMPORTS_PER_SOL)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Normal Transfer With SignTransaction', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const toPubkey = getRandWallet();
const recentBlockhash = getRandWallet();
const lamports = ((getRandInt(10000000) + 1) / 10000000.0) * LAMPORTS_PER_SOL;
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
toPubkey,
recentBlockhash,
lamports,
},
addressIndex: 0,
};
const signedTx = await sol.signTransaction(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = new Transaction({
feePayer: expectedWallet.publicKey,
recentBlockhash,
}).add(
SystemProgram.transfer({
fromPubkey: expectedWallet.publicKey,
toPubkey: new PublicKey(toPubkey),
lamports,
})
);
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Normal Transfer params', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.addressPage(toPubkey)
.amountPage(+lamports / LAMPORTS_PER_SOL)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Staking Withdraw with different toPubkey', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const lamports = ((getRandInt(10000000) + 1) / 10000000.0) * LAMPORTS_PER_SOL;
const recentBlockhash = getRandWallet();
const stakePubkey = getRandWallet();
const withdrawToPubKey = getRandWallet();
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
stakePubkey,
withdrawToPubKey,
recentBlockhash,
lamports,
},
addressIndex: 0,
};
const signedTx = await sol.signTransaction(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = StakeProgram.withdraw({
authorizedPubkey: expectedWallet.publicKey,
lamports,
stakePubkey: new PublicKey(stakePubkey),
toPubkey: new PublicKey(withdrawToPubKey),
});
expectedTransaction.feePayer = expectedWallet.publicKey;
expectedTransaction.recentBlockhash = recentBlockhash;
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Staking Withdraw params', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.messagePage('Reward')
.addressPage(withdrawToPubKey)
.amountPage(+lamports / LAMPORTS_PER_SOL)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
it('Test Staking Withdraw with Same toPubkey', async () => {
const addressIndex = 0;
const node = wallet.derivePath(bip32Path(addressIndex));
const expectedWallet = Keypair.fromSeed(node.privateKey);
const lamports = ((getRandInt(10000000) + 1) / 10000000.0) * LAMPORTS_PER_SOL;
const recentBlockhash = getRandWallet();
const stakePubkey = getRandWallet();
const withdrawToPubKey = expectedWallet.publicKey;
const signTxData = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
transaction: {
stakePubkey,
withdrawToPubKey: withdrawToPubKey.toString(),
recentBlockhash,
lamports,
},
addressIndex: 0,
};
const signedTx = await sol.signTransaction(signTxData);
const recoveredTx = Transaction.from(Buffer.from(signedTx, 'hex'));
const expectedTransaction = StakeProgram.withdraw({
authorizedPubkey: withdrawToPubKey,
lamports,
stakePubkey: new PublicKey(stakePubkey),
toPubkey: withdrawToPubKey,
});
expectedTransaction.feePayer = expectedWallet.publicKey;
expectedTransaction.recentBlockhash = recentBlockhash;
const message = expectedTransaction.compileMessage();
const expectedSignature = (await node.sign(message.serialize().toString('hex'))) ?? new Uint8Array();
expectedTransaction.addSignature(expectedWallet.publicKey, Buffer.from(expectedSignature));
try {
expect(recoveredTx.verifySignatures()).toEqual(true);
expect(expectedTransaction.verifySignatures()).toEqual(true);
expect(recoveredTx.serialize().toString('hex')).toEqual(expectedTransaction.serialize().toString('hex'));
} catch (e) {
console.error('Test Staking Withdraw params', signTxData.transaction);
throw e;
}
const display = await getTxDetail(transport, props.appId);
const expectedTxDetail = new DisplayBuilder()
.messagePage('TEST')
.messagePage('SOL')
.messagePage('Reward')
.addressPage(withdrawToPubKey.toString())
.amountPage(+lamports / LAMPORTS_PER_SOL)
.wrapPage('PRESS', 'BUTToN')
.finalize();
expect(display).toEqual(expectedTxDetail.toLowerCase());
});
});