At this moment whirlpools SDK have building/signing/sending tx steps meshed together. Trying to separate transaction signing into separate secure environment.
- generate transaction without private key, send to signer as string
[typescript]
// walletAddr is public key, same as signer. private key is not available
const whirlpool = await client.getPool(whirlpoolAddress);
const tx = await whirlpool.swap(quote, walletAddr);
const result = await tx.build();
const txs = result.transaction.serialize({ requireAllSignatures: false, verifySignatures: true });
return Buffer.from(txs).toString('base64');
- sign transaction and send to network
const keypair = Keypair.fromSecretKey(new Uint8Array(secret));
const signers = [keypair];
let vt = VersionedTransaction.deserialize(Buffer.from(txB64string, 'base64'));
vt.sign(signers);
const connection = new Connection("https://api.mainnet-beta.solana.com", 'confirmed');
await connection.sendTransaction(vt);
except it doesn't work, failed to send transaction: Transaction signature verification failure
P.S. key line is Whirlpools-specific tx.build()
, and for some reason it generates two empty (all zeroes) signatures, adding real one makes it 3 total. removing empty ones by hand gives various errors depending on transaction header and remaining signatures
P.S. The solution was:
- replace wallet manually
const tx = await whirlpoolPool.swap(quote, walletAddr);
let w = new ReadOnlyWallet(walletAddr);
(tx.wallet as any) = w;
- do not use fresh wallet, create associated token accounts before using them