@fogo/sessions-sdk 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Connection, TransactionError, TransactionInstruction, VersionedTransaction } from "@solana/web3.js";
2
- import { PublicKey } from "@solana/web3.js";
1
+ import type { Connection, TransactionError, VersionedTransaction } from "@solana/web3.js";
2
+ import { PublicKey, TransactionInstruction } from "@solana/web3.js";
3
3
  import type { Chain } from "@wormhole-foundation/sdk";
4
4
  import BN from "bn.js";
5
5
  import { z } from "zod";
package/cjs/index.js CHANGED
@@ -464,12 +464,80 @@ const buildStartSessionIntentInstruction = async (options, sessionKey, tokens) =
464
464
  const buildIntentInstruction = async (options, header, body, extra) => {
465
465
  const message = new TextEncoder().encode([header, serializeKV(body), extra && serializeExtra(extra)].join("\n"));
466
466
  const { signature, signedMessage } = await options.signMessage(message);
467
- return web3_js_1.Ed25519Program.createInstructionWithPublicKey({
468
- message: signedMessage,
469
- publicKey: options.walletPublicKey.toBytes(),
470
- signature,
467
+ const publicKey = options.walletPublicKey.toBytes();
468
+ const publicKeyOffsetInMessage = getOffchainMessagePublicKeyOffset(signedMessage, options.walletPublicKey);
469
+ if (publicKeyOffsetInMessage !== undefined) {
470
+ return buildEd25519InstructionWithOffsets({
471
+ message: signedMessage,
472
+ publicKeyOffsetInMessage,
473
+ signature,
474
+ });
475
+ }
476
+ else {
477
+ return web3_js_1.Ed25519Program.createInstructionWithPublicKey({
478
+ message: signedMessage,
479
+ publicKey,
480
+ signature,
481
+ });
482
+ }
483
+ };
484
+ const ED25519_HEADER_LEN = 16;
485
+ const ED25519_PUBLIC_KEY_LEN = 32;
486
+ const ED25519_SIGNATURE_LEN = 64;
487
+ const ED25519_CURRENT_INSTRUCTION_INDEX = 0xff_ff;
488
+ const buildEd25519InstructionWithOffsets = (params) => {
489
+ const { signature, message, publicKeyOffsetInMessage } = params;
490
+ if (signature.length !== ED25519_SIGNATURE_LEN) {
491
+ throw new Error(`Signature must be ${ED25519_SIGNATURE_LEN} bytes but received ${signature.length} bytes`);
492
+ }
493
+ if (publicKeyOffsetInMessage < 0 ||
494
+ publicKeyOffsetInMessage + ED25519_PUBLIC_KEY_LEN > message.length) {
495
+ throw new Error("Public key offset is out of bounds of signed message");
496
+ }
497
+ const signatureOffset = ED25519_HEADER_LEN;
498
+ const messageDataOffset = signatureOffset + signature.length;
499
+ const publicKeyOffsetInInstruction = messageDataOffset + publicKeyOffsetInMessage;
500
+ const instructionData = new Uint8Array(ED25519_HEADER_LEN + ED25519_SIGNATURE_LEN + message.length);
501
+ const view = new DataView(instructionData.buffer);
502
+ view.setUint8(0, 1); // num_signatures
503
+ view.setUint8(1, 0); // padding
504
+ view.setUint16(2, signatureOffset, true);
505
+ view.setUint16(4, ED25519_CURRENT_INSTRUCTION_INDEX, true);
506
+ view.setUint16(6, publicKeyOffsetInInstruction, true);
507
+ view.setUint16(8, ED25519_CURRENT_INSTRUCTION_INDEX, true);
508
+ view.setUint16(10, messageDataOffset, true);
509
+ view.setUint16(12, message.length, true);
510
+ view.setUint16(14, ED25519_CURRENT_INSTRUCTION_INDEX, true);
511
+ instructionData.set(signature, signatureOffset);
512
+ instructionData.set(message, messageDataOffset);
513
+ return new web3_js_1.TransactionInstruction({
514
+ data: Buffer.from(instructionData),
515
+ keys: [],
516
+ programId: web3_js_1.Ed25519Program.programId,
471
517
  });
472
518
  };
519
+ const OFFCHAIN_SIGNING_DOMAIN_LEN = 16;
520
+ const OFFCHAIN_V0_SIGNER_LIST_OFFSET = OFFCHAIN_SIGNING_DOMAIN_LEN + 1 + 32 + 1 + 1;
521
+ const OFFCHAIN_V1_SIGNER_LIST_OFFSET = OFFCHAIN_SIGNING_DOMAIN_LEN + 1 + 1;
522
+ const getOffchainMessagePublicKeyOffset = (signedMessage, publicKey) => {
523
+ const address = publicKey.toBase58();
524
+ try {
525
+ const message = (0, kit_1.getOffchainMessageDecoder)().decode(signedMessage);
526
+ const index = message.requiredSignatories.findIndex((signer) => signer.address === address);
527
+ if (index !== -1) {
528
+ const baseOffset = message.version === 1
529
+ ? OFFCHAIN_V1_SIGNER_LIST_OFFSET
530
+ : OFFCHAIN_V0_SIGNER_LIST_OFFSET;
531
+ return baseOffset + index * ED25519_PUBLIC_KEY_LEN;
532
+ }
533
+ else {
534
+ return undefined;
535
+ }
536
+ }
537
+ catch {
538
+ return undefined;
539
+ }
540
+ };
473
541
  const serializeExtra = (extra) => {
474
542
  for (const [key, value] of Object.entries(extra)) {
475
543
  if (!/^[a-z]+(_[a-z0-9]+)*$/.test(key)) {
package/esm/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Connection, TransactionError, TransactionInstruction, VersionedTransaction } from "@solana/web3.js";
2
- import { PublicKey } from "@solana/web3.js";
1
+ import type { Connection, TransactionError, VersionedTransaction } from "@solana/web3.js";
2
+ import { PublicKey, TransactionInstruction } from "@solana/web3.js";
3
3
  import type { Chain } from "@wormhole-foundation/sdk";
4
4
  import BN from "bn.js";
5
5
  import { z } from "zod";
package/esm/index.js CHANGED
@@ -5,9 +5,9 @@ import { publicKey as metaplexPublicKey } from "@metaplex-foundation/umi";
5
5
  import { createUmi } from "@metaplex-foundation/umi-bundle-defaults";
6
6
  import { sha256 } from "@noble/hashes/sha2.js";
7
7
  import { fromLegacyPublicKey } from "@solana/compat";
8
- import { generateKeyPair, getAddressFromPublicKey, getProgramDerivedAddress, } from "@solana/kit";
8
+ import { generateKeyPair, getAddressFromPublicKey, getOffchainMessageDecoder, getProgramDerivedAddress, } from "@solana/kit";
9
9
  import { getAssociatedTokenAddressSync, getMint } from "@solana/spl-token";
10
- import { ComputeBudgetProgram, Ed25519Program, Keypair, PublicKey, } from "@solana/web3.js";
10
+ import { ComputeBudgetProgram, Ed25519Program, Keypair, PublicKey, TransactionInstruction, } from "@solana/web3.js";
11
11
  import { Wormhole, wormhole } from "@wormhole-foundation/sdk";
12
12
  import solanaSdk from "@wormhole-foundation/sdk/solana";
13
13
  import { contracts } from "@wormhole-foundation/sdk-base";
@@ -411,12 +411,80 @@ const buildStartSessionIntentInstruction = async (options, sessionKey, tokens) =
411
411
  const buildIntentInstruction = async (options, header, body, extra) => {
412
412
  const message = new TextEncoder().encode([header, serializeKV(body), extra && serializeExtra(extra)].join("\n"));
413
413
  const { signature, signedMessage } = await options.signMessage(message);
414
- return Ed25519Program.createInstructionWithPublicKey({
415
- message: signedMessage,
416
- publicKey: options.walletPublicKey.toBytes(),
417
- signature,
414
+ const publicKey = options.walletPublicKey.toBytes();
415
+ const publicKeyOffsetInMessage = getOffchainMessagePublicKeyOffset(signedMessage, options.walletPublicKey);
416
+ if (publicKeyOffsetInMessage !== undefined) {
417
+ return buildEd25519InstructionWithOffsets({
418
+ message: signedMessage,
419
+ publicKeyOffsetInMessage,
420
+ signature,
421
+ });
422
+ }
423
+ else {
424
+ return Ed25519Program.createInstructionWithPublicKey({
425
+ message: signedMessage,
426
+ publicKey,
427
+ signature,
428
+ });
429
+ }
430
+ };
431
+ const ED25519_HEADER_LEN = 16;
432
+ const ED25519_PUBLIC_KEY_LEN = 32;
433
+ const ED25519_SIGNATURE_LEN = 64;
434
+ const ED25519_CURRENT_INSTRUCTION_INDEX = 0xff_ff;
435
+ const buildEd25519InstructionWithOffsets = (params) => {
436
+ const { signature, message, publicKeyOffsetInMessage } = params;
437
+ if (signature.length !== ED25519_SIGNATURE_LEN) {
438
+ throw new Error(`Signature must be ${ED25519_SIGNATURE_LEN} bytes but received ${signature.length} bytes`);
439
+ }
440
+ if (publicKeyOffsetInMessage < 0 ||
441
+ publicKeyOffsetInMessage + ED25519_PUBLIC_KEY_LEN > message.length) {
442
+ throw new Error("Public key offset is out of bounds of signed message");
443
+ }
444
+ const signatureOffset = ED25519_HEADER_LEN;
445
+ const messageDataOffset = signatureOffset + signature.length;
446
+ const publicKeyOffsetInInstruction = messageDataOffset + publicKeyOffsetInMessage;
447
+ const instructionData = new Uint8Array(ED25519_HEADER_LEN + ED25519_SIGNATURE_LEN + message.length);
448
+ const view = new DataView(instructionData.buffer);
449
+ view.setUint8(0, 1); // num_signatures
450
+ view.setUint8(1, 0); // padding
451
+ view.setUint16(2, signatureOffset, true);
452
+ view.setUint16(4, ED25519_CURRENT_INSTRUCTION_INDEX, true);
453
+ view.setUint16(6, publicKeyOffsetInInstruction, true);
454
+ view.setUint16(8, ED25519_CURRENT_INSTRUCTION_INDEX, true);
455
+ view.setUint16(10, messageDataOffset, true);
456
+ view.setUint16(12, message.length, true);
457
+ view.setUint16(14, ED25519_CURRENT_INSTRUCTION_INDEX, true);
458
+ instructionData.set(signature, signatureOffset);
459
+ instructionData.set(message, messageDataOffset);
460
+ return new TransactionInstruction({
461
+ data: Buffer.from(instructionData),
462
+ keys: [],
463
+ programId: Ed25519Program.programId,
418
464
  });
419
465
  };
466
+ const OFFCHAIN_SIGNING_DOMAIN_LEN = 16;
467
+ const OFFCHAIN_V0_SIGNER_LIST_OFFSET = OFFCHAIN_SIGNING_DOMAIN_LEN + 1 + 32 + 1 + 1;
468
+ const OFFCHAIN_V1_SIGNER_LIST_OFFSET = OFFCHAIN_SIGNING_DOMAIN_LEN + 1 + 1;
469
+ const getOffchainMessagePublicKeyOffset = (signedMessage, publicKey) => {
470
+ const address = publicKey.toBase58();
471
+ try {
472
+ const message = getOffchainMessageDecoder().decode(signedMessage);
473
+ const index = message.requiredSignatories.findIndex((signer) => signer.address === address);
474
+ if (index !== -1) {
475
+ const baseOffset = message.version === 1
476
+ ? OFFCHAIN_V1_SIGNER_LIST_OFFSET
477
+ : OFFCHAIN_V0_SIGNER_LIST_OFFSET;
478
+ return baseOffset + index * ED25519_PUBLIC_KEY_LEN;
479
+ }
480
+ else {
481
+ return undefined;
482
+ }
483
+ }
484
+ catch {
485
+ return undefined;
486
+ }
487
+ };
420
488
  const serializeExtra = (extra) => {
421
489
  for (const [key, value] of Object.entries(extra)) {
422
490
  if (!/^[a-z]+(_[a-z0-9]+)*$/.test(key)) {
package/package.json CHANGED
@@ -51,5 +51,5 @@
51
51
  },
52
52
  "type": "module",
53
53
  "types": "./cjs/index.d.ts",
54
- "version": "0.1.9"
54
+ "version": "0.1.10"
55
55
  }