Skip to content

Commit 000d269

Browse files
authored
solana: versioning (#400)
* solana: versioning * solana: bump VERSION to 1.0.0
1 parent 3bb0c4c commit 000d269

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

solana/programs/example-native-token-transfers/src/lib.rs

+9
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ pub const TOKEN_AUTHORITY_SEED: &[u8] = b"token_authority";
6262
/// user, atomically).
6363
pub const SESSION_AUTHORITY_SEED: &[u8] = b"session_authority";
6464

65+
pub const VERSION: &str = "1.0.0";
66+
6567
#[program]
6668
pub mod example_native_token_transfers {
6769

@@ -71,6 +73,10 @@ pub mod example_native_token_transfers {
7173
instructions::initialize(ctx, args)
7274
}
7375

76+
pub fn version(_ctx: Context<Version>) -> Result<String> {
77+
Ok(VERSION.to_string())
78+
}
79+
7480
pub fn transfer_burn(ctx: Context<TransferBurn>, args: TransferArgs) -> Result<()> {
7581
instructions::transfer_burn(ctx, args)
7682
}
@@ -162,3 +168,6 @@ pub mod example_native_token_transfers {
162168
transceivers::wormhole::instructions::broadcast_peer(ctx, args)
163169
}
164170
}
171+
172+
#[derive(Accounts)]
173+
pub struct Version {}

solana/tests/example-native-token-transfer.ts

+5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ describe("example-native-token-transfers", () => {
7070
);
7171
});
7272

73+
it("Can check version", async () => {
74+
const version = await ntt.version(payer.publicKey);
75+
expect(version).to.equal("1.0.0");
76+
});
77+
7378
describe("Locking", () => {
7479
before(async () => {
7580
await spl.setAuthority(

solana/ts/sdk/ntt.ts

+42-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
nativeTokenTransferLayout
1111
} from './nttLayout'
1212
import { derivePostedVaaKey, getWormholeDerivedAccounts } from '@certusone/wormhole-sdk/lib/cjs/solana/wormhole'
13-
import { BN, translateError, type IdlAccounts, Program } from '@coral-xyz/anchor'
13+
import { BN, translateError, type IdlAccounts, Program, AnchorProvider, Wallet, } from '@coral-xyz/anchor'
1414
import { associatedAddress } from '@coral-xyz/anchor/dist/cjs/utils/token'
1515
import { getAssociatedTokenAddressSync } from '@solana/spl-token'
1616
import {
@@ -19,7 +19,9 @@ import {
1919
Transaction,
2020
sendAndConfirmTransaction,
2121
type TransactionSignature,
22-
type Connection
22+
type Connection,
23+
TransactionMessage,
24+
VersionedTransaction
2325
} from '@solana/web3.js'
2426
import { Keccak } from 'sha3'
2527
import { type ExampleNativeTokenTransfers as RawExampleNativeTokenTransfers } from '../../target/types/example_native_token_transfers'
@@ -170,6 +172,44 @@ export class NTT {
170172
return this.derivePda(['registered_transceiver', transceiver.toBytes()])
171173
}
172174

175+
// View functions
176+
177+
async version(pubkey: PublicKey): Promise<string> {
178+
// the anchor library has a built-in method to read view functions. However,
179+
// it requires a signer, which would trigger a wallet prompt on the frontend.
180+
// Instead, we manually construct a versioned transaction and call the
181+
// simulate function with sigVerify: false below.
182+
//
183+
// This way, the simulation won't require a signer, but it still requires
184+
// the pubkey of an account that has some lamports in it (since the
185+
// simulation checks if the account has enough money to pay for the transaction).
186+
//
187+
// It's a little unfortunate but it's the best we can do.
188+
const ix = await this.program.methods.version()
189+
.accountsStrict({}).instruction()
190+
const latestBlockHash = await this.program.provider.connection.getLatestBlockhash()
191+
192+
const msg = new TransactionMessage({
193+
payerKey: pubkey,
194+
recentBlockhash: latestBlockHash.blockhash,
195+
instructions: [ix],
196+
}).compileToV0Message();
197+
198+
const tx = new VersionedTransaction(msg);
199+
200+
const txSimulation =
201+
await this.program.provider.connection
202+
.simulateTransaction(tx, {
203+
sigVerify: false,
204+
})
205+
206+
// the return buffer is in base64 and it encodes the string with a 32 bit
207+
// little endian length prefix.
208+
const buffer = Buffer.from(txSimulation.value.returnData?.data[0], 'base64')
209+
const len = buffer.readUInt32LE(0)
210+
return buffer.slice(4, len + 4).toString()
211+
}
212+
173213
// Instructions
174214

175215
async initialize(args: {

0 commit comments

Comments
 (0)