@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.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.mts +274 -84
- package/dist/index.d.ts +274 -84
- package/dist/index.js +444 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +442 -48
- package/dist/index.mjs.map +1 -1
- package/examples/evm/policies/createAccountPolicy.ts +68 -0
- package/examples/evm/policies/createProjectPolicy.ts +53 -0
- package/examples/evm/policies/deletePolicy.ts +34 -0
- package/examples/evm/policies/getPolicyById.ts +34 -0
- package/examples/evm/policies/listAccountPolicies.ts +11 -0
- package/examples/evm/policies/listPolicies.ts +11 -0
- package/examples/evm/policies/listProjectPolicies.ts +11 -0
- package/examples/evm/policies/signTypedDataPolicy.ts +35 -0
- package/examples/evm/policies/updatePolicy.ts +44 -0
- package/examples/evm/policies/validation.ts +45 -0
- package/examples/evm/transactions/sendTransaction.ts +44 -0
- package/examples/package.json +13 -0
- package/examples/pnpm-lock.yaml +933 -0
- package/examples/solana/accounts/importAccount.ts +14 -8
- package/examples/solana/policies/createSolAllowlistPolicy.ts +27 -0
- package/examples/solana/policies/createSolMessagePolicy.ts +29 -0
- package/examples/solana/policies/createSplTokenLimitsPolicy.ts +33 -0
- package/examples/solana/signing/signTransaction.ts +42 -21
- package/examples/solana/transactions/sendRawTransaction.ts +23 -0
- package/examples/solana/transactions/sendTransaction.ts +37 -0
- package/examples/solana/transactions/transfer.ts +44 -0
- package/knip.json +10 -1
- package/package.json +42 -4
- package/tsconfig.json +2 -3
- package/examples/policies/createAccountPolicy.ts +0 -71
- package/examples/policies/createEvmPolicy.ts +0 -149
- package/examples/policies/createSolanaPolicy.ts +0 -176
- package/examples/policies/createTypedDataPolicy.ts +0 -159
- package/examples/policies/deletePolicy.ts +0 -34
- package/examples/policies/getPolicy.ts +0 -41
- package/examples/policies/listPolicies.ts +0 -34
- package/examples/policies/multiRulePolicy.ts +0 -133
- package/examples/policies/updatePolicy.ts +0 -77
- package/examples/policies/validatePolicy.ts +0 -176
- /package/examples/{contracts → evm/contracts}/createContract.ts +0 -0
- /package/examples/{contracts → evm/contracts}/listContracts.ts +0 -0
- /package/examples/{transactions → evm/transactionIntents}/createTransactionIntent.ts +0 -0
- /package/examples/{transactions → evm/transactionIntents}/estimateGas.ts +0 -0
- /package/examples/{transactions → evm/transactionIntents}/getTransactionIntent.ts +0 -0
- /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
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
4288
|
-
const signedTransaction =
|
|
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:
|
|
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 =
|
|
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 ===
|
|
4749
|
-
|
|
4750
|
-
|
|
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
|
|
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 ?
|
|
4849
|
-
const allChains = Object.values(
|
|
4850
|
-
const chain = allChains.find(
|
|
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:
|
|
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 =
|
|
5280
|
+
const publicClient = viem.createPublicClient({ chain, transport });
|
|
4874
5281
|
const eoaNonce = await publicClient.getTransactionCount({
|
|
4875
5282
|
address: account.address
|
|
4876
5283
|
});
|
|
4877
|
-
const authHash =
|
|
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,
|
|
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 {
|