BREAKING CHANGE: requires Solana version v0.13.0 or greater
feat: Update to current solana tx format
This commit is contained in:
committed by
Michael Vines
parent
853ea88fd0
commit
efd0392706
@@ -203,7 +203,7 @@ export class BudgetProgram {
|
||||
}
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, to],
|
||||
keys: [{pubkey: from, isSigner: true}, {pubkey: to, isSigner: false}],
|
||||
programId: this.programId,
|
||||
data: data.slice(0, pos),
|
||||
});
|
||||
@@ -223,7 +223,11 @@ export class BudgetProgram {
|
||||
}
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, program, to],
|
||||
keys: [
|
||||
{pubkey: from, isSigner: true},
|
||||
{pubkey: program, isSigner: false},
|
||||
{pubkey: to, isSigner: false},
|
||||
],
|
||||
programId: this.programId,
|
||||
data: data.slice(0, pos),
|
||||
});
|
||||
@@ -243,7 +247,11 @@ export class BudgetProgram {
|
||||
}
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, program, to],
|
||||
keys: [
|
||||
{pubkey: from, isSigner: true},
|
||||
{pubkey: program, isSigner: false},
|
||||
{pubkey: to, isSigner: false},
|
||||
],
|
||||
programId: this.programId,
|
||||
data: data.slice(0, pos),
|
||||
});
|
||||
@@ -287,7 +295,11 @@ export class BudgetProgram {
|
||||
pos += paymentData.length;
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, program, to],
|
||||
keys: [
|
||||
{pubkey: from, isSigner: true},
|
||||
{pubkey: program, isSigner: false},
|
||||
{pubkey: to, isSigner: false},
|
||||
],
|
||||
programId: this.programId,
|
||||
data: data.slice(0, pos),
|
||||
});
|
||||
@@ -310,7 +322,11 @@ export class BudgetProgram {
|
||||
whenData.copy(data, 4);
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, program, to],
|
||||
keys: [
|
||||
{pubkey: from, isSigner: true},
|
||||
{pubkey: program, isSigner: false},
|
||||
{pubkey: to, isSigner: false},
|
||||
],
|
||||
programId: this.programId,
|
||||
data,
|
||||
});
|
||||
@@ -336,7 +352,11 @@ export class BudgetProgram {
|
||||
);
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, program, to],
|
||||
keys: [
|
||||
{pubkey: from, isSigner: true},
|
||||
{pubkey: program, isSigner: false},
|
||||
{pubkey: to, isSigner: false},
|
||||
],
|
||||
programId: this.programId,
|
||||
data,
|
||||
});
|
||||
|
@@ -75,7 +75,7 @@ export class Loader {
|
||||
);
|
||||
|
||||
const transaction = new Transaction().add({
|
||||
keys: [program.publicKey],
|
||||
keys: [{pubkey: program.publicKey, isSigner: true}],
|
||||
programId: this.programId,
|
||||
data,
|
||||
});
|
||||
@@ -119,7 +119,7 @@ export class Loader {
|
||||
);
|
||||
|
||||
const transaction = new Transaction().add({
|
||||
keys: [program.publicKey],
|
||||
keys: [{pubkey: program.publicKey, isSigner: true}],
|
||||
programId: this.programId,
|
||||
data,
|
||||
});
|
||||
|
@@ -48,7 +48,10 @@ export class SystemProgram {
|
||||
);
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, newAccount],
|
||||
keys: [
|
||||
{pubkey: from, isSigner: true},
|
||||
{pubkey: newAccount, isSigner: false},
|
||||
],
|
||||
programId: SystemProgram.programId,
|
||||
data,
|
||||
});
|
||||
@@ -73,7 +76,7 @@ export class SystemProgram {
|
||||
);
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from, to],
|
||||
keys: [{pubkey: from, isSigner: true}, {pubkey: to, isSigner: false}],
|
||||
programId: SystemProgram.programId,
|
||||
data,
|
||||
});
|
||||
@@ -98,7 +101,7 @@ export class SystemProgram {
|
||||
);
|
||||
|
||||
return new Transaction().add({
|
||||
keys: [from],
|
||||
keys: [{pubkey: from, isSigner: true}],
|
||||
programId: SystemProgram.programId,
|
||||
data,
|
||||
});
|
||||
|
@@ -236,11 +236,13 @@ export class Token {
|
||||
await sendAndConfirmTransaction(connection, transaction, owner);
|
||||
|
||||
transaction = new Transaction().add({
|
||||
keys: [tokenAccount.publicKey, initialAccountPublicKey],
|
||||
keys: [
|
||||
{pubkey: tokenAccount.publicKey, isSigner: true},
|
||||
{pubkey: initialAccountPublicKey, isSigner: false},
|
||||
],
|
||||
programId,
|
||||
data,
|
||||
});
|
||||
transaction.fee = 0; // TODO: Batch with the `SystemProgram.createAccount` and remove this line
|
||||
await sendAndConfirmTransaction(connection, transaction, tokenAccount);
|
||||
|
||||
return [token, initialAccountPublicKey];
|
||||
@@ -284,16 +286,19 @@ export class Token {
|
||||
await sendAndConfirmTransaction(this.connection, transaction, owner);
|
||||
|
||||
// Initialize the token account
|
||||
const keys = [tokenAccount.publicKey, owner.publicKey, this.token];
|
||||
const keys = [
|
||||
{pubkey: tokenAccount.publicKey, isSigner: true},
|
||||
{pubkey: owner.publicKey, isSigner: false},
|
||||
{pubkey: this.token, isSigner: false},
|
||||
];
|
||||
if (source) {
|
||||
keys.push(source);
|
||||
keys.push({pubkey: source, isSigner: false});
|
||||
}
|
||||
transaction = new Transaction().add({
|
||||
keys,
|
||||
programId: this.programId,
|
||||
data,
|
||||
});
|
||||
transaction.fee = 0; // TODO: Batch with the `SystemProgram.createAccount` and remove this line
|
||||
await sendAndConfirmTransaction(this.connection, transaction, tokenAccount);
|
||||
|
||||
return tokenAccount.publicKey;
|
||||
@@ -480,9 +485,13 @@ export class Token {
|
||||
data,
|
||||
);
|
||||
|
||||
const keys = [owner, source, destination];
|
||||
const keys = [
|
||||
{pubkey: owner, isSigner: true},
|
||||
{pubkey: source, isSigner: false},
|
||||
{pubkey: destination, isSigner: false},
|
||||
];
|
||||
if (accountInfo.source) {
|
||||
keys.push(accountInfo.source);
|
||||
keys.push({pubkey: accountInfo.source, isSigner: false});
|
||||
}
|
||||
return new TransactionInstruction({
|
||||
keys,
|
||||
@@ -520,7 +529,11 @@ export class Token {
|
||||
);
|
||||
|
||||
return new TransactionInstruction({
|
||||
keys: [owner, account, delegate],
|
||||
keys: [
|
||||
{pubkey: owner, isSigner: true},
|
||||
{pubkey: account, isSigner: false},
|
||||
{pubkey: delegate, isSigner: false},
|
||||
],
|
||||
programId: this.programId,
|
||||
data,
|
||||
});
|
||||
@@ -564,7 +577,11 @@ export class Token {
|
||||
);
|
||||
|
||||
return new TransactionInstruction({
|
||||
keys: [owner, account, newOwner],
|
||||
keys: [
|
||||
{pubkey: owner, isSigner: true},
|
||||
{pubkey: account, isSigner: false},
|
||||
{pubkey: newOwner, isSigner: false},
|
||||
],
|
||||
programId: this.programId,
|
||||
data,
|
||||
});
|
||||
|
@@ -30,7 +30,7 @@ export const PACKET_DATA_SIZE = 512;
|
||||
* @property {?Buffer} data
|
||||
*/
|
||||
type TransactionInstructionCtorFields = {|
|
||||
keys?: Array<PublicKey>,
|
||||
keys?: Array<{pubkey: PublicKey, isSigner: boolean}>,
|
||||
programId?: PublicKey,
|
||||
data?: Buffer,
|
||||
|};
|
||||
@@ -41,8 +41,9 @@ type TransactionInstructionCtorFields = {|
|
||||
export class TransactionInstruction {
|
||||
/**
|
||||
* Public keys to include in this transaction
|
||||
* Boolean represents whether this pubkey needs to sign the transaction
|
||||
*/
|
||||
keys: Array<PublicKey> = [];
|
||||
keys: Array<{pubkey: PublicKey, isSigner: boolean}> = [];
|
||||
|
||||
/**
|
||||
* Program Id to execute
|
||||
@@ -71,13 +72,11 @@ type SignaturePubkeyPair = {|
|
||||
* List of Transaction object fields that may be initialized at construction
|
||||
*
|
||||
* @typedef {Object} TransactionCtorFields
|
||||
* @property {?number} fee
|
||||
* @property (?recentBlockhash} A recent block hash
|
||||
* @property (?signatures} One or more signatures
|
||||
*
|
||||
*/
|
||||
type TransactionCtorFields = {|
|
||||
fee?: number,
|
||||
recentBlockhash?: Blockhash,
|
||||
signatures?: Array<SignaturePubkeyPair>,
|
||||
|};
|
||||
@@ -112,11 +111,6 @@ export class Transaction {
|
||||
*/
|
||||
recentBlockhash: ?Blockhash;
|
||||
|
||||
/**
|
||||
* Fee for this transaction
|
||||
*/
|
||||
fee: number = 1;
|
||||
|
||||
/**
|
||||
* Construct an empty Transaction
|
||||
*/
|
||||
@@ -158,6 +152,7 @@ export class Transaction {
|
||||
}
|
||||
|
||||
const keys = this.signatures.map(({publicKey}) => publicKey.toString());
|
||||
let numRequiredSignatures = 0;
|
||||
|
||||
const programIds = [];
|
||||
this.instructions.forEach(instruction => {
|
||||
@@ -166,13 +161,15 @@ export class Transaction {
|
||||
programIds.push(programId);
|
||||
}
|
||||
|
||||
instruction.keys
|
||||
.map(key => key.toString())
|
||||
.forEach(key => {
|
||||
if (!keys.includes(key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
});
|
||||
instruction.keys.forEach(keySignerPair => {
|
||||
const keyStr = keySignerPair.pubkey.toString();
|
||||
if (keySignerPair.isSigner) {
|
||||
numRequiredSignatures += 1;
|
||||
}
|
||||
if (!keys.includes(keyStr)) {
|
||||
keys.push(keyStr);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let keyCount = [];
|
||||
@@ -191,7 +188,9 @@ export class Transaction {
|
||||
programIdIndex: programIds.indexOf(programId.toString()),
|
||||
keyIndicesCount: Buffer.from(keyIndicesCount),
|
||||
keyIndices: Buffer.from(
|
||||
instruction.keys.map(key => keys.indexOf(key.toString())),
|
||||
instruction.keys.map(keyObj =>
|
||||
keys.indexOf(keyObj.pubkey.toString()),
|
||||
),
|
||||
),
|
||||
dataLength: Buffer.from(dataCount),
|
||||
data,
|
||||
@@ -239,10 +238,10 @@ export class Transaction {
|
||||
instructionBuffer = instructionBuffer.slice(0, instructionBufferLength);
|
||||
|
||||
const signDataLayout = BufferLayout.struct([
|
||||
BufferLayout.blob(1, 'numRequiredSignatures'),
|
||||
BufferLayout.blob(keyCount.length, 'keyCount'),
|
||||
BufferLayout.seq(Layout.publicKey('key'), keys.length, 'keys'),
|
||||
Layout.publicKey('recentBlockhash'),
|
||||
BufferLayout.ns64('fee'),
|
||||
|
||||
BufferLayout.blob(programIdCount.length, 'programIdCount'),
|
||||
BufferLayout.seq(
|
||||
@@ -253,10 +252,10 @@ export class Transaction {
|
||||
]);
|
||||
|
||||
const transaction = {
|
||||
numRequiredSignatures: Buffer.from([numRequiredSignatures]),
|
||||
keyCount: Buffer.from(keyCount),
|
||||
keys: keys.map(key => new PublicKey(key).toBuffer()),
|
||||
recentBlockhash: Buffer.from(bs58.decode(recentBlockhash)),
|
||||
fee: this.fee,
|
||||
programIdCount: Buffer.from(programIdCount),
|
||||
programIds: programIds.map(programId =>
|
||||
new PublicKey(programId).toBuffer(),
|
||||
@@ -389,7 +388,7 @@ export class Transaction {
|
||||
*/
|
||||
get keys(): Array<PublicKey> {
|
||||
invariant(this.instructions.length === 1);
|
||||
return this.instructions[0].keys;
|
||||
return this.instructions[0].keys.map(keyObj => keyObj.pubkey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -430,6 +429,8 @@ export class Transaction {
|
||||
signatures.push(signature);
|
||||
}
|
||||
|
||||
byteArray = byteArray.slice(1); // Skip numRequiredSignatures byte
|
||||
|
||||
const accountCount = shortvec.decodeLength(byteArray);
|
||||
let accounts = [];
|
||||
for (let i = 0; i < accountCount; i++) {
|
||||
@@ -441,11 +442,6 @@ export class Transaction {
|
||||
const recentBlockhash = byteArray.slice(0, PUBKEY_LENGTH);
|
||||
byteArray = byteArray.slice(PUBKEY_LENGTH);
|
||||
|
||||
let fee = 0;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
fee += byteArray.shift() >> (8 * i);
|
||||
}
|
||||
|
||||
const programIdCount = shortvec.decodeLength(byteArray);
|
||||
let programs = [];
|
||||
for (let i = 0; i < programIdCount; i++) {
|
||||
@@ -470,7 +466,6 @@ export class Transaction {
|
||||
|
||||
// Populate Transaction object
|
||||
transaction.recentBlockhash = new PublicKey(recentBlockhash).toBase58();
|
||||
transaction.fee = fee;
|
||||
for (let i = 0; i < signatureCount; i++) {
|
||||
const sigPubkeyPair = {
|
||||
signature: Buffer.from(signatures[i]),
|
||||
@@ -485,9 +480,13 @@ export class Transaction {
|
||||
data: Buffer.from(instructions[i].data),
|
||||
};
|
||||
for (let j = 0; j < instructions[i].accountIndex.length; j++) {
|
||||
instructionData.keys.push(
|
||||
new PublicKey(accounts[instructions[i].accountIndex[j]]),
|
||||
);
|
||||
const pubkey = new PublicKey(accounts[instructions[i].accountIndex[j]]);
|
||||
instructionData.keys.push({
|
||||
pubkey,
|
||||
isSigner: transaction.signatures.some(
|
||||
keyObj => keyObj.publicKey.toString() === pubkey.toString(),
|
||||
),
|
||||
});
|
||||
}
|
||||
let instruction = new TransactionInstruction(instructionData);
|
||||
transaction.instructions.push(instruction);
|
||||
|
Reference in New Issue
Block a user