@openfort/openfort-node 0.9.3 → 0.10.1

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.d.mts +274 -84
  3. package/dist/index.d.ts +274 -84
  4. package/dist/index.js +444 -40
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +442 -48
  7. package/dist/index.mjs.map +1 -1
  8. package/examples/evm/policies/createAccountPolicy.ts +68 -0
  9. package/examples/evm/policies/createProjectPolicy.ts +53 -0
  10. package/examples/evm/policies/deletePolicy.ts +34 -0
  11. package/examples/evm/policies/getPolicyById.ts +34 -0
  12. package/examples/evm/policies/listAccountPolicies.ts +11 -0
  13. package/examples/evm/policies/listPolicies.ts +11 -0
  14. package/examples/evm/policies/listProjectPolicies.ts +11 -0
  15. package/examples/evm/policies/signTypedDataPolicy.ts +35 -0
  16. package/examples/evm/policies/updatePolicy.ts +44 -0
  17. package/examples/evm/policies/validation.ts +45 -0
  18. package/examples/evm/transactions/sendTransaction.ts +44 -0
  19. package/examples/package.json +13 -0
  20. package/examples/pnpm-lock.yaml +933 -0
  21. package/examples/solana/accounts/importAccount.ts +14 -8
  22. package/examples/solana/policies/createSolAllowlistPolicy.ts +27 -0
  23. package/examples/solana/policies/createSolMessagePolicy.ts +29 -0
  24. package/examples/solana/policies/createSplTokenLimitsPolicy.ts +33 -0
  25. package/examples/solana/signing/signTransaction.ts +42 -21
  26. package/examples/solana/transactions/sendRawTransaction.ts +23 -0
  27. package/examples/solana/transactions/sendTransaction.ts +37 -0
  28. package/examples/solana/transactions/transfer.ts +44 -0
  29. package/knip.json +10 -1
  30. package/package.json +42 -4
  31. package/tsconfig.json +2 -3
  32. package/examples/policies/createAccountPolicy.ts +0 -71
  33. package/examples/policies/createEvmPolicy.ts +0 -149
  34. package/examples/policies/createSolanaPolicy.ts +0 -176
  35. package/examples/policies/createTypedDataPolicy.ts +0 -159
  36. package/examples/policies/deletePolicy.ts +0 -34
  37. package/examples/policies/getPolicy.ts +0 -41
  38. package/examples/policies/listPolicies.ts +0 -34
  39. package/examples/policies/multiRulePolicy.ts +0 -133
  40. package/examples/policies/updatePolicy.ts +0 -77
  41. package/examples/policies/validatePolicy.ts +0 -176
  42. /package/examples/{contracts → evm/contracts}/createContract.ts +0 -0
  43. /package/examples/{contracts → evm/contracts}/listContracts.ts +0 -0
  44. /package/examples/{transactions → evm/transactionIntents}/createTransactionIntent.ts +0 -0
  45. /package/examples/{transactions → evm/transactionIntents}/estimateGas.ts +0 -0
  46. /package/examples/{transactions → evm/transactionIntents}/getTransactionIntent.ts +0 -0
  47. /package/examples/{transactions → evm/transactionIntents}/listTransactionIntents.ts +0 -0
package/dist/index.js CHANGED
@@ -467,7 +467,7 @@ __export(index_exports, {
467
467
  verifyOAuthToken: () => verifyOAuthToken
468
468
  });
469
469
  module.exports = __toCommonJS(index_exports);
470
- var import_node_crypto4 = require("crypto");
470
+ var import_node_crypto5 = require("crypto");
471
471
  var import_shield_js = require("@openfort/shield-js");
472
472
  var import_node_fetch = __toESM(require("node-fetch"));
473
473
 
@@ -842,7 +842,7 @@ function requiresWalletAuth(requestMethod, requestPath) {
842
842
  }
843
843
 
844
844
  // src/version.ts
845
- var VERSION = "0.9.3";
845
+ var VERSION = "0.10.1";
846
846
  var PACKAGE = "@openfort/openfort-node";
847
847
 
848
848
  // src/openapi-client/openfortApiClient.ts
@@ -4238,9 +4238,6 @@ var decryptExportedPrivateKey = (encryptedPrivateKeyBase64, privateKeyPem) => {
4238
4238
  return decrypted.toString("hex");
4239
4239
  };
4240
4240
 
4241
- // src/wallets/evm/accounts/evmAccount.ts
4242
- var import_viem = require("viem");
4243
-
4244
4241
  // src/wallets/evm/actions/normalizeSignature.ts
4245
4242
  function normalizeSignature(sig) {
4246
4243
  const v = parseInt(sig.slice(-2), 16);
@@ -4276,29 +4273,53 @@ function toEvmAccount(data) {
4276
4273
  return result.signature;
4277
4274
  },
4278
4275
  async signMessage(parameters) {
4276
+ let viem;
4277
+ try {
4278
+ viem = await import("viem");
4279
+ } catch {
4280
+ throw new UserInputValidationError(
4281
+ "`viem` is required for signMessage. Install it and try again."
4282
+ );
4283
+ }
4279
4284
  const { message } = parameters;
4280
- const preimage = (0, import_viem.toPrefixedMessage)(message);
4285
+ const preimage = viem.toPrefixedMessage(message);
4281
4286
  const result = await sign(id, { data: preimage });
4282
- return result.signature;
4287
+ return normalizeSignature(result.signature);
4283
4288
  },
4284
4289
  async signTransaction(transaction) {
4285
- const serialized = (0, import_viem.serializeTransaction)(transaction);
4290
+ let viem;
4291
+ try {
4292
+ viem = await import("viem");
4293
+ } catch {
4294
+ throw new UserInputValidationError(
4295
+ "`viem` is required for signTransaction. Install it and try again."
4296
+ );
4297
+ }
4298
+ const serialized = viem.serializeTransaction(transaction);
4286
4299
  const response = await sign(id, { data: serialized });
4287
- const signature2 = (0, import_viem.parseSignature)(response.signature);
4288
- const signedTransaction = (0, import_viem.serializeTransaction)(
4300
+ const signature2 = viem.parseSignature(response.signature);
4301
+ const signedTransaction = viem.serializeTransaction(
4289
4302
  transaction,
4290
4303
  signature2
4291
4304
  );
4292
4305
  return signedTransaction;
4293
4306
  },
4294
4307
  async signTypedData(parameters) {
4308
+ let viem;
4309
+ try {
4310
+ viem = await import("viem");
4311
+ } catch {
4312
+ throw new UserInputValidationError(
4313
+ "`viem` is required for signTypedData. Install it and try again."
4314
+ );
4315
+ }
4295
4316
  const {
4296
4317
  domain = {},
4297
4318
  message,
4298
4319
  primaryType
4299
4320
  } = parameters;
4300
4321
  const types = {
4301
- EIP712Domain: (0, import_viem.getTypesForEIP712Domain)({ domain }),
4322
+ EIP712Domain: viem.getTypesForEIP712Domain({ domain }),
4302
4323
  ...parameters.types
4303
4324
  };
4304
4325
  const openApiMessage = {
@@ -4307,9 +4328,9 @@ function toEvmAccount(data) {
4307
4328
  primaryType,
4308
4329
  message
4309
4330
  };
4310
- const hash = (0, import_viem.hashTypedData)(openApiMessage);
4331
+ const hash = viem.hashTypedData(openApiMessage);
4311
4332
  const result = await sign(id, { data: hash });
4312
- return result.signature;
4333
+ return normalizeSignature(result.signature);
4313
4334
  }
4314
4335
  };
4315
4336
  return account;
@@ -4409,6 +4430,12 @@ var EvmClient = class {
4409
4430
  }
4410
4431
  throw new AccountNotFoundError();
4411
4432
  }
4433
+ /**
4434
+ * Retrieves delegated accounts linked to an EVM address on a specific chain.
4435
+ *
4436
+ * @param options - Options containing the address and chain ID
4437
+ * @returns List of linked accounts
4438
+ */
4412
4439
  async getLinkedAccounts(options) {
4413
4440
  const response = await getAccountsV2({
4414
4441
  address: options.address,
@@ -4545,8 +4572,201 @@ var EvmClient = class {
4545
4572
  EvmClient.type = "evmWallet";
4546
4573
 
4547
4574
  // src/wallets/solana/solanaClient.ts
4575
+ var import_node_crypto4 = require("crypto");
4548
4576
  var import_bs58 = __toESM(require("bs58"));
4549
4577
 
4578
+ // src/wallets/solana/actions/constants.ts
4579
+ var USDC_MAINNET_MINT_ADDRESS = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
4580
+ var USDC_DEVNET_MINT_ADDRESS = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU";
4581
+ var DEFAULT_COMPUTE_UNIT_LIMIT = 2e5;
4582
+ var DEFAULT_COMPUTE_UNIT_PRICE = 50000n;
4583
+
4584
+ // src/wallets/solana/actions/utils.ts
4585
+ function getUsdcMintAddress(cluster) {
4586
+ if (cluster === "mainnet-beta") {
4587
+ return USDC_MAINNET_MINT_ADDRESS;
4588
+ }
4589
+ return USDC_DEVNET_MINT_ADDRESS;
4590
+ }
4591
+ function getRpcEndpoint(cluster) {
4592
+ return cluster === "mainnet-beta" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
4593
+ }
4594
+ function getWsEndpoint(cluster) {
4595
+ return cluster === "mainnet-beta" ? "wss://api.mainnet-beta.solana.com" : "wss://api.devnet.solana.com";
4596
+ }
4597
+
4598
+ // src/wallets/solana/actions/sendTransaction.ts
4599
+ async function sendTransaction(options) {
4600
+ const {
4601
+ account,
4602
+ cluster,
4603
+ instructions,
4604
+ computeUnitLimit,
4605
+ computeUnitPrice,
4606
+ rpcUrl,
4607
+ wsUrl
4608
+ } = options;
4609
+ let solanaKit;
4610
+ let computeBudget;
4611
+ let transactionConfirmation;
4612
+ let koraModule;
4613
+ try {
4614
+ solanaKit = await import("@solana/kit");
4615
+ } catch {
4616
+ throw new UserInputValidationError(
4617
+ "`@solana/kit` is required for sendTransaction. Install it and try again."
4618
+ );
4619
+ }
4620
+ try {
4621
+ computeBudget = await import("@solana-program/compute-budget");
4622
+ } catch {
4623
+ throw new UserInputValidationError(
4624
+ "`@solana-program/compute-budget` is required for sendTransaction. Install it and try again."
4625
+ );
4626
+ }
4627
+ try {
4628
+ koraModule = await import("@solana/kora");
4629
+ } catch {
4630
+ throw new UserInputValidationError(
4631
+ "`@solana/kora` is required for sendTransaction. Install it and try again."
4632
+ );
4633
+ }
4634
+ try {
4635
+ transactionConfirmation = await import("@solana/transaction-confirmation");
4636
+ } catch {
4637
+ throw new UserInputValidationError(
4638
+ "`@solana/transaction-confirmation` is required for sendTransaction. Install it and try again."
4639
+ );
4640
+ }
4641
+ const userAddress = solanaKit.address(account.address);
4642
+ const clientConfig2 = getConfig();
4643
+ if (!clientConfig2?.publishableKey) {
4644
+ throw new MissingPublishableKeyError("sendTransaction");
4645
+ }
4646
+ const basePath = clientConfig2.basePath || "https://api.openfort.io";
4647
+ const client = new koraModule.KoraClient({
4648
+ rpcUrl: `${basePath}/rpc/solana/${cluster}`,
4649
+ apiKey: `Bearer ${clientConfig2.publishableKey}`
4650
+ });
4651
+ const rpc = solanaKit.createSolanaRpc(rpcUrl ?? getRpcEndpoint(cluster));
4652
+ const rpcSubscriptions = solanaKit.createSolanaRpcSubscriptions(
4653
+ wsUrl ?? getWsEndpoint(cluster)
4654
+ );
4655
+ const confirmTransaction = transactionConfirmation.createRecentSignatureConfirmationPromiseFactory({
4656
+ rpc,
4657
+ rpcSubscriptions
4658
+ });
4659
+ const { signer_address } = await client.getPayerSigner();
4660
+ const blockhashResponse = await client.getBlockhash();
4661
+ let txMsg = solanaKit.pipe(
4662
+ solanaKit.createTransactionMessage({ version: 0 }),
4663
+ (tx) => solanaKit.setTransactionMessageFeePayer(
4664
+ solanaKit.address(signer_address),
4665
+ tx
4666
+ ),
4667
+ // Kora's getBlockhash does not return lastValidBlockHeight, so we use 0n.
4668
+ // Transaction expiry is handled by the confirmTransaction timeout instead.
4669
+ (tx) => solanaKit.setTransactionMessageLifetimeUsingBlockhash(
4670
+ {
4671
+ blockhash: blockhashResponse.blockhash,
4672
+ lastValidBlockHeight: 0n
4673
+ },
4674
+ tx
4675
+ ),
4676
+ (tx) => solanaKit.appendTransactionMessageInstructions(instructions, tx),
4677
+ (tx) => computeBudget.updateOrAppendSetComputeUnitPriceInstruction(
4678
+ computeUnitPrice ?? DEFAULT_COMPUTE_UNIT_PRICE,
4679
+ tx
4680
+ ),
4681
+ (tx) => computeBudget.updateOrAppendSetComputeUnitLimitInstruction(
4682
+ computeUnitLimit ?? DEFAULT_COMPUTE_UNIT_LIMIT,
4683
+ tx
4684
+ )
4685
+ );
4686
+ if (computeUnitLimit === void 0) {
4687
+ const estimateComputeUnitLimit = computeBudget.estimateComputeUnitLimitFactory({ rpc });
4688
+ try {
4689
+ const estimatedLimit = await estimateComputeUnitLimit(txMsg);
4690
+ txMsg = computeBudget.updateOrAppendSetComputeUnitLimitInstruction(
4691
+ estimatedLimit,
4692
+ txMsg
4693
+ );
4694
+ } catch {
4695
+ }
4696
+ }
4697
+ const compiled = solanaKit.compileTransaction(txMsg);
4698
+ const messageBase64 = Buffer.from(
4699
+ compiled.messageBytes
4700
+ ).toString("base64");
4701
+ const signatureHex = await account.signTransaction({
4702
+ transaction: messageBase64
4703
+ });
4704
+ const sigBytes = new Uint8Array(
4705
+ Buffer.from(signatureHex.replace(/^0x/, ""), "hex")
4706
+ );
4707
+ const EMPTY_SIGNATURE = new Uint8Array(64);
4708
+ const signatures = Object.fromEntries(
4709
+ Object.entries(compiled.signatures).map(([addr]) => [
4710
+ addr,
4711
+ addr === userAddress ? sigBytes : EMPTY_SIGNATURE
4712
+ ])
4713
+ );
4714
+ const signed = { ...compiled, signatures };
4715
+ const base64Full = solanaKit.getBase64EncodedWireTransaction(signed);
4716
+ const { signed_transaction } = await client.signTransaction({
4717
+ transaction: base64Full,
4718
+ signer_key: signer_address
4719
+ });
4720
+ const signature2 = await rpc.sendTransaction(
4721
+ signed_transaction,
4722
+ { encoding: "base64" }
4723
+ ).send();
4724
+ await confirmTransaction({
4725
+ commitment: "confirmed",
4726
+ signature: signature2,
4727
+ abortSignal: AbortSignal.timeout(6e4)
4728
+ });
4729
+ return { signature: signature2 };
4730
+ }
4731
+
4732
+ // src/wallets/solana/actions/sendRawTransaction.ts
4733
+ async function sendRawTransaction(options) {
4734
+ const {
4735
+ account,
4736
+ cluster,
4737
+ transaction,
4738
+ computeUnitLimit,
4739
+ computeUnitPrice,
4740
+ rpcUrl,
4741
+ wsUrl
4742
+ } = options;
4743
+ let solanaKit;
4744
+ try {
4745
+ solanaKit = await import("@solana/kit");
4746
+ } catch {
4747
+ throw new UserInputValidationError(
4748
+ "`@solana/kit` is required for sendRawTransaction. Install it and try again."
4749
+ );
4750
+ }
4751
+ const txBytes = new Uint8Array(Buffer.from(transaction, "base64"));
4752
+ const decoded = solanaKit.getTransactionDecoder().decode(txBytes);
4753
+ const compiledMessage = solanaKit.getCompiledTransactionMessageDecoder().decode(decoded.messageBytes);
4754
+ const rpc = solanaKit.createSolanaRpc(rpcUrl ?? getRpcEndpoint(cluster));
4755
+ const decompiled = await solanaKit.decompileTransactionMessageFetchingLookupTables(
4756
+ compiledMessage,
4757
+ rpc
4758
+ );
4759
+ return sendTransaction({
4760
+ account,
4761
+ cluster,
4762
+ instructions: [...decompiled.instructions],
4763
+ computeUnitLimit,
4764
+ computeUnitPrice,
4765
+ rpcUrl,
4766
+ wsUrl
4767
+ });
4768
+ }
4769
+
4550
4770
  // src/wallets/solana/actions/signMessage.ts
4551
4771
  async function signMessage(options) {
4552
4772
  const { accountId, message } = options;
@@ -4569,6 +4789,150 @@ async function signTransaction(options) {
4569
4789
  };
4570
4790
  }
4571
4791
 
4792
+ // src/wallets/solana/actions/rpc.ts
4793
+ async function createRpcClient(cluster, rpcUrl) {
4794
+ let solanaKit;
4795
+ try {
4796
+ solanaKit = await import("@solana/kit");
4797
+ } catch {
4798
+ throw new UserInputValidationError(
4799
+ "`@solana/kit` is required. Install it and try again."
4800
+ );
4801
+ }
4802
+ return solanaKit.createSolanaRpc(rpcUrl ?? getRpcEndpoint(cluster));
4803
+ }
4804
+
4805
+ // src/wallets/solana/actions/transfer.ts
4806
+ async function transfer(options) {
4807
+ const { account, cluster, rpcUrl, ...rest } = options;
4808
+ const rpc = await createRpcClient(cluster, rpcUrl);
4809
+ const instructions = !options.token || options.token.toLowerCase() === "sol" ? await getNativeTransferInstructions({
4810
+ from: account.address,
4811
+ to: options.to,
4812
+ amount: options.amount
4813
+ }) : await getSplTransferInstructions({
4814
+ rpc,
4815
+ from: account.address,
4816
+ to: options.to,
4817
+ mintAddress: options.token.toLowerCase() === "usdc" ? getUsdcMintAddress(cluster) : options.token,
4818
+ amount: options.amount
4819
+ });
4820
+ return sendTransaction({
4821
+ account,
4822
+ cluster,
4823
+ instructions,
4824
+ rpcUrl,
4825
+ computeUnitLimit: rest.computeUnitLimit,
4826
+ computeUnitPrice: rest.computeUnitPrice,
4827
+ wsUrl: rest.wsUrl
4828
+ });
4829
+ }
4830
+ async function getNativeTransferInstructions({
4831
+ from,
4832
+ to,
4833
+ amount
4834
+ }) {
4835
+ let solanaKit;
4836
+ let systemProgram;
4837
+ try {
4838
+ solanaKit = await import("@solana/kit");
4839
+ } catch {
4840
+ throw new UserInputValidationError(
4841
+ "`@solana/kit` is required for transfer. Install it and try again."
4842
+ );
4843
+ }
4844
+ try {
4845
+ systemProgram = await import("@solana-program/system");
4846
+ } catch {
4847
+ throw new UserInputValidationError(
4848
+ "`@solana-program/system` is required for SOL transfers. Install it and try again."
4849
+ );
4850
+ }
4851
+ const fromAddr = solanaKit.address(from);
4852
+ const toAddr = solanaKit.address(to);
4853
+ return [
4854
+ systemProgram.getTransferSolInstruction({
4855
+ source: solanaKit.createNoopSigner(fromAddr),
4856
+ destination: toAddr,
4857
+ amount
4858
+ })
4859
+ ];
4860
+ }
4861
+ async function getSplTransferInstructions({
4862
+ rpc,
4863
+ from,
4864
+ to,
4865
+ mintAddress,
4866
+ amount
4867
+ }) {
4868
+ let solanaKit;
4869
+ let tokenProgram;
4870
+ try {
4871
+ solanaKit = await import("@solana/kit");
4872
+ } catch {
4873
+ throw new UserInputValidationError(
4874
+ "`@solana/kit` is required for transfer. Install it and try again."
4875
+ );
4876
+ }
4877
+ try {
4878
+ tokenProgram = await import("@solana-program/token");
4879
+ } catch {
4880
+ throw new UserInputValidationError(
4881
+ "`@solana-program/token` is required for SPL transfers. Install it and try again."
4882
+ );
4883
+ }
4884
+ const fromAddr = solanaKit.address(from);
4885
+ const toAddr = solanaKit.address(to);
4886
+ const mintAddr = solanaKit.address(mintAddress);
4887
+ const mintInfo = await tokenProgram.fetchMint(rpc, mintAddr).catch(() => {
4888
+ throw new UserInputValidationError(
4889
+ `Failed to fetch mint account for ${mintAddress}. Verify the mint address is correct.`
4890
+ );
4891
+ });
4892
+ const [sourceAta] = await tokenProgram.findAssociatedTokenPda({
4893
+ mint: mintAddr,
4894
+ owner: fromAddr,
4895
+ tokenProgram: tokenProgram.TOKEN_PROGRAM_ADDRESS
4896
+ });
4897
+ const [destAta] = await tokenProgram.findAssociatedTokenPda({
4898
+ mint: mintAddr,
4899
+ owner: toAddr,
4900
+ tokenProgram: tokenProgram.TOKEN_PROGRAM_ADDRESS
4901
+ });
4902
+ const sourceAcct = await tokenProgram.fetchToken(rpc, sourceAta).catch(() => {
4903
+ throw new UserInputValidationError(
4904
+ `Source account has no token account for mint ${mintAddress}`
4905
+ );
4906
+ });
4907
+ if (sourceAcct.data.amount < amount) {
4908
+ throw new UserInputValidationError(
4909
+ `Insufficient token balance: have ${sourceAcct.data.amount}, need ${amount}`
4910
+ );
4911
+ }
4912
+ const instructions = [];
4913
+ const destAccountInfo = await rpc.getAccountInfo(destAta, { encoding: "base64" }).send();
4914
+ if (!destAccountInfo.value) {
4915
+ const createDestIx = await tokenProgram.getCreateAssociatedTokenInstructionAsync({
4916
+ payer: solanaKit.createNoopSigner(fromAddr),
4917
+ owner: toAddr,
4918
+ ata: destAta,
4919
+ mint: mintAddr
4920
+ });
4921
+ instructions.push(createDestIx);
4922
+ }
4923
+ instructions.push(
4924
+ tokenProgram.getTransferCheckedInstruction({
4925
+ source: sourceAta,
4926
+ mint: mintAddr,
4927
+ destination: destAta,
4928
+ authority: solanaKit.createNoopSigner(fromAddr),
4929
+ amount,
4930
+ decimals: mintInfo.data.decimals
4931
+ })
4932
+ );
4933
+ return instructions;
4934
+ }
4935
+
4572
4936
  // src/wallets/solana/accounts/solanaAccount.ts
4573
4937
  function toSolanaAccount(data) {
4574
4938
  const { id, address } = data;
@@ -4589,6 +4953,12 @@ function toSolanaAccount(data) {
4589
4953
  transaction: parameters.transaction
4590
4954
  });
4591
4955
  return result.signedTransaction;
4956
+ },
4957
+ async transfer(options) {
4958
+ return transfer({ ...options, account });
4959
+ },
4960
+ async sendRawTransaction(options) {
4961
+ return sendRawTransaction({ ...options, account });
4592
4962
  }
4593
4963
  };
4594
4964
  return account;
@@ -4745,9 +5115,24 @@ var SolanaClient = class {
4745
5115
  );
4746
5116
  }
4747
5117
  }
4748
- if (privateKeyBytes.length === 64) {
4749
- privateKeyBytes = privateKeyBytes.slice(0, 32);
4750
- } else if (privateKeyBytes.length !== 32) {
5118
+ if (privateKeyBytes.length === 32) {
5119
+ const edPrivKey = (0, import_node_crypto4.createPrivateKey)({
5120
+ key: Buffer.concat([
5121
+ Buffer.from(
5122
+ // PKCS#8 DER prefix for Ed25519 (RFC 8410): 16 bytes wrapping a 32-byte seed
5123
+ "302e020100300506032b657004220420",
5124
+ "hex"
5125
+ ),
5126
+ privateKeyBytes
5127
+ ]),
5128
+ format: "der",
5129
+ type: "pkcs8"
5130
+ });
5131
+ const rawPublicKey = (0, import_node_crypto4.createPublicKey)(edPrivKey).export({ type: "spki", format: "der" }).subarray(-32);
5132
+ privateKeyBytes = new Uint8Array(
5133
+ Buffer.concat([privateKeyBytes, rawPublicKey])
5134
+ );
5135
+ } else if (privateKeyBytes.length !== 64) {
4751
5136
  throw new UserInputValidationError(
4752
5137
  "Private key must be 32 bytes (seed) or 64 bytes (full keypair)"
4753
5138
  );
@@ -4819,16 +5204,12 @@ var SolanaClient = class {
4819
5204
  return response.signature;
4820
5205
  }
4821
5206
  };
5207
+ /** Wallet type identifier used for client registration */
4822
5208
  SolanaClient.type = "solanaWallet";
4823
5209
 
4824
5210
  // src/index.ts
4825
5211
  var import_shield_js2 = require("@openfort/shield-js");
4826
5212
 
4827
- // src/wallets/evm/actions/sendTransaction.ts
4828
- var import_viem2 = require("viem");
4829
- var chains = __toESM(require("viem/chains"));
4830
- var import_utils = require("viem/utils");
4831
-
4832
5213
  // src/wallets/evm/actions/updateToDelegated.ts
4833
5214
  async function update(options) {
4834
5215
  const { chainId, walletId, implementationType, accountId } = options;
@@ -4843,11 +5224,37 @@ async function update(options) {
4843
5224
  }
4844
5225
 
4845
5226
  // src/wallets/evm/actions/sendTransaction.ts
4846
- async function sendTransaction(options) {
5227
+ async function sendTransaction2(options) {
5228
+ let viem;
5229
+ let viemChains;
5230
+ let viemUtils;
5231
+ try {
5232
+ viem = await import("viem");
5233
+ } catch {
5234
+ throw new UserInputValidationError(
5235
+ "`viem` is required for sendTransaction. Install it and try again."
5236
+ );
5237
+ }
5238
+ try {
5239
+ viemChains = await import("viem/chains");
5240
+ } catch {
5241
+ throw new UserInputValidationError(
5242
+ "`viem` is required for sendTransaction. Install it and try again."
5243
+ );
5244
+ }
5245
+ try {
5246
+ viemUtils = await import("viem/utils");
5247
+ } catch {
5248
+ throw new UserInputValidationError(
5249
+ "`viem` is required for sendTransaction. Install it and try again."
5250
+ );
5251
+ }
4847
5252
  const { account, chainId, interactions, policy, rpcUrl } = options;
4848
- const transport = rpcUrl ? (0, import_viem2.http)(rpcUrl) : (0, import_viem2.http)();
4849
- const allChains = Object.values(chains);
4850
- const chain = allChains.find((c) => c.id === chainId);
5253
+ const transport = rpcUrl ? viem.http(rpcUrl) : viem.http();
5254
+ const allChains = Object.values(viemChains);
5255
+ const chain = allChains.find(
5256
+ (c) => typeof c === "object" && c !== null && "id" in c && c.id === chainId
5257
+ );
4851
5258
  if (!chain) {
4852
5259
  throw new DelegationError(
4853
5260
  `Unknown chain ID ${chainId}. Provide a custom rpcUrl for unsupported chains.`
@@ -4856,7 +5263,7 @@ async function sendTransaction(options) {
4856
5263
  let signedAuthorization;
4857
5264
  let txAccountId;
4858
5265
  const response = await getAccountsV2({
4859
- address: (0, import_viem2.getAddress)(account.address),
5266
+ address: viem.getAddress(account.address),
4860
5267
  accountType: "Delegated Account",
4861
5268
  chainType: "EVM",
4862
5269
  chainId
@@ -4870,11 +5277,11 @@ async function sendTransaction(options) {
4870
5277
  });
4871
5278
  txAccountId = updated.id;
4872
5279
  const implementationAddress = "0x000000009b1d0af20d8c6d0a44e162d11f9b8f00";
4873
- const publicClient = (0, import_viem2.createPublicClient)({ chain, transport });
5280
+ const publicClient = viem.createPublicClient({ chain, transport });
4874
5281
  const eoaNonce = await publicClient.getTransactionCount({
4875
5282
  address: account.address
4876
5283
  });
4877
- const authHash = (0, import_utils.hashAuthorization)({
5284
+ const authHash = viemUtils.hashAuthorization({
4878
5285
  contractAddress: implementationAddress,
4879
5286
  chainId,
4880
5287
  nonce: eoaNonce
@@ -4901,15 +5308,6 @@ async function sendTransaction(options) {
4901
5308
  });
4902
5309
  }
4903
5310
 
4904
- // src/wallets/evm/actions/signMessage.ts
4905
- var import_viem3 = require("viem");
4906
-
4907
- // src/wallets/evm/actions/signTransaction.ts
4908
- var import_viem4 = require("viem");
4909
-
4910
- // src/wallets/evm/actions/signTypedData.ts
4911
- var import_viem5 = require("viem");
4912
-
4913
5311
  // src/policies/evmSchema.ts
4914
5312
  var import_zod = require("zod");
4915
5313
  var EthValueOperatorEnum = import_zod.z.enum(["<=", ">=", "<", ">"]);
@@ -5312,7 +5710,7 @@ var Openfort = class {
5312
5710
  /** Update EOA to delegated account */
5313
5711
  update,
5314
5712
  /** Delegate + create + sign + submit a gasless transaction in one call */
5315
- sendTransaction
5713
+ sendTransaction: sendTransaction2
5316
5714
  },
5317
5715
  /** Embedded wallet operations (User custody) */
5318
5716
  embedded: {
@@ -5341,7 +5739,13 @@ var Openfort = class {
5341
5739
  /** Import private key (with E2E encryption) */
5342
5740
  import: solanaClient.importAccount.bind(solanaClient),
5343
5741
  /** Export private key (with E2E encryption) */
5344
- export: solanaClient.exportAccount.bind(solanaClient)
5742
+ export: solanaClient.exportAccount.bind(solanaClient),
5743
+ /** Send a gasless transaction via Kora */
5744
+ sendTransaction,
5745
+ /** Send a pre-built base64 transaction via Kora gasless flow */
5746
+ sendRawTransaction,
5747
+ /** Transfer SOL or SPL tokens (high-level) */
5748
+ transfer
5345
5749
  },
5346
5750
  /** Embedded wallet operations (User custody) */
5347
5751
  embedded: {
@@ -5819,7 +6223,7 @@ var Openfort = class {
5819
6223
  const signedPayload = await sign2(this._apiKey, body);
5820
6224
  const expectedBuffer = Buffer.from(signedPayload, "hex");
5821
6225
  const receivedBuffer = Buffer.from(signature2, "hex");
5822
- if (expectedBuffer.length !== receivedBuffer.length || !(0, import_node_crypto4.timingSafeEqual)(expectedBuffer, receivedBuffer)) {
6226
+ if (expectedBuffer.length !== receivedBuffer.length || !(0, import_node_crypto5.timingSafeEqual)(expectedBuffer, receivedBuffer)) {
5823
6227
  throw new Error("Invalid signature");
5824
6228
  }
5825
6229
  try {