-
Notifications
You must be signed in to change notification settings - Fork 274
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3780 from BitGo/EA-1169-sdk-create-raw-message-au…
…thorize-builder feat(sdk-coin-sol): add raw msg authorize builder
- Loading branch information
Showing
12 changed files
with
427 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
modules/sdk-coin-sol/src/lib/stakingRawMsgAuthorizeBuilder.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import { BaseCoin as CoinConfig } from '@bitgo/statics'; | ||
import { | ||
BaseAddress, | ||
BaseKey, | ||
BaseTransaction, | ||
BaseTransactionBuilder, | ||
NotSupported, | ||
TransactionType, | ||
} from '@bitgo/sdk-core'; | ||
import { Transaction } from './transaction'; | ||
import { | ||
Transaction as SOLTransaction, | ||
Message as SOLMessage, | ||
SystemProgram, | ||
SystemInstruction, | ||
StakeProgram, | ||
} from '@solana/web3.js'; | ||
|
||
import assert from 'assert'; | ||
import BigNumber from 'bignumber.js'; | ||
import { nonceAdvanceInstruction, validInstructionData } from './constants'; | ||
|
||
export class StakingRawMsgAuthorizeBuilder extends BaseTransactionBuilder { | ||
protected _transaction: Transaction; | ||
protected _transactionMessage: string; | ||
constructor(_coinConfig: Readonly<CoinConfig>) { | ||
super(_coinConfig); | ||
this._transaction = new Transaction(_coinConfig); | ||
} | ||
|
||
protected get transactionType(): TransactionType { | ||
return TransactionType.StakingAuthorizeRaw; | ||
} | ||
|
||
/** @inheritdoc */ | ||
initBuilder(tx: Transaction): void { | ||
if (this.validateTransaction(tx)) { | ||
this.transactionMessage(tx.solTransaction.serializeMessage().toString('base64')); | ||
} | ||
} | ||
|
||
/** | ||
* The raw message generated by Solana CLI. | ||
* | ||
* @param {string} msg msg generated by 'solana stake-authorize-check. | ||
* @returns {StakeBuilder} This staking builder. | ||
* | ||
*/ | ||
transactionMessage(msg: string): this { | ||
this.validateMessage(msg); | ||
this._transactionMessage = msg; | ||
return this; | ||
} | ||
|
||
/** @inheritdoc */ | ||
protected async buildImplementation(): Promise<Transaction> { | ||
assert(this._transactionMessage, 'missing transaction message'); | ||
|
||
this.validateMessage(this._transactionMessage); | ||
this.transaction.solTransaction = SOLTransaction.populate( | ||
SOLMessage.from(Buffer.from(this._transactionMessage, 'base64')), | ||
[] | ||
); | ||
this.transaction.setTransactionType(this.transactionType); | ||
return this.transaction; | ||
} | ||
|
||
validateTransaction(tx: Transaction): boolean { | ||
return this.validateMessage(tx.solTransaction.serializeMessage().toString('base64')); | ||
} | ||
|
||
async build(): Promise<Transaction> { | ||
return this.buildImplementation(); | ||
} | ||
|
||
protected validateMessage(msg: string): boolean { | ||
const tx = SOLTransaction.populate(SOLMessage.from(Buffer.from(msg, 'base64')), []); | ||
const instructions = tx.instructions; | ||
if (instructions.length !== 2) { | ||
throw new Error(`Invalid transaction, expected 2 instruction, got ${instructions.length}`); | ||
} | ||
for (const instruction of instructions) { | ||
switch (instruction.programId.toString()) { | ||
case SystemProgram.programId.toString(): | ||
const instructionName = SystemInstruction.decodeInstructionType(instruction); | ||
if (instructionName !== nonceAdvanceInstruction) { | ||
throw new Error(`Invalid system instruction : ${instructionName}`); | ||
} | ||
break; | ||
case StakeProgram.programId.toString(): | ||
const data = instruction.data.toString('hex'); | ||
if (data !== validInstructionData) { | ||
throw new Error(`Invalid staking instruction data: ${data}`); | ||
} | ||
break; | ||
default: | ||
throw new Error( | ||
`Invalid transaction, instruction program id not supported: ${instruction.programId.toString()}` | ||
); | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
protected fromImplementation(rawTransaction: string): Transaction { | ||
const tx = new Transaction(this._coinConfig); | ||
tx.fromRawTransaction(rawTransaction); | ||
this.initBuilder(tx); | ||
return this.transaction; | ||
} | ||
|
||
protected signImplementation(key: BaseKey): BaseTransaction { | ||
throw new NotSupported('Method not supported on this builder'); | ||
} | ||
|
||
protected get transaction(): Transaction { | ||
return this._transaction; | ||
} | ||
|
||
validateAddress(address: BaseAddress, addressFormat?: string): void { | ||
throw new NotSupported('Method not supported on this builder'); | ||
} | ||
|
||
validateKey(key: BaseKey): void { | ||
throw new NotSupported('Method not supported on this builder'); | ||
} | ||
|
||
validateRawTransaction(rawTransaction: string): void { | ||
const tx = new Transaction(this._coinConfig); | ||
tx.fromRawTransaction(rawTransaction); | ||
this.validateTransaction(tx); | ||
} | ||
|
||
validateValue(value: BigNumber): void { | ||
throw new NotSupported('Method not supported on this builder'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.