@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.mjs
CHANGED
|
@@ -384,7 +384,7 @@ function requiresWalletAuth(requestMethod, requestPath) {
|
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
// src/version.ts
|
|
387
|
-
var VERSION = "0.
|
|
387
|
+
var VERSION = "0.10.1";
|
|
388
388
|
var PACKAGE = "@openfort/openfort-node";
|
|
389
389
|
|
|
390
390
|
// src/openapi-client/openfortApiClient.ts
|
|
@@ -3785,15 +3785,6 @@ var decryptExportedPrivateKey = (encryptedPrivateKeyBase64, privateKeyPem) => {
|
|
|
3785
3785
|
return decrypted.toString("hex");
|
|
3786
3786
|
};
|
|
3787
3787
|
|
|
3788
|
-
// src/wallets/evm/accounts/evmAccount.ts
|
|
3789
|
-
import {
|
|
3790
|
-
getTypesForEIP712Domain,
|
|
3791
|
-
hashTypedData,
|
|
3792
|
-
parseSignature,
|
|
3793
|
-
serializeTransaction,
|
|
3794
|
-
toPrefixedMessage
|
|
3795
|
-
} from "viem";
|
|
3796
|
-
|
|
3797
3788
|
// src/wallets/evm/actions/normalizeSignature.ts
|
|
3798
3789
|
function normalizeSignature(sig) {
|
|
3799
3790
|
const v = parseInt(sig.slice(-2), 16);
|
|
@@ -3829,29 +3820,53 @@ function toEvmAccount(data) {
|
|
|
3829
3820
|
return result.signature;
|
|
3830
3821
|
},
|
|
3831
3822
|
async signMessage(parameters) {
|
|
3823
|
+
let viem;
|
|
3824
|
+
try {
|
|
3825
|
+
viem = await import("viem");
|
|
3826
|
+
} catch {
|
|
3827
|
+
throw new UserInputValidationError(
|
|
3828
|
+
"`viem` is required for signMessage. Install it and try again."
|
|
3829
|
+
);
|
|
3830
|
+
}
|
|
3832
3831
|
const { message } = parameters;
|
|
3833
|
-
const preimage = toPrefixedMessage(message);
|
|
3832
|
+
const preimage = viem.toPrefixedMessage(message);
|
|
3834
3833
|
const result = await sign(id, { data: preimage });
|
|
3835
|
-
return result.signature;
|
|
3834
|
+
return normalizeSignature(result.signature);
|
|
3836
3835
|
},
|
|
3837
3836
|
async signTransaction(transaction) {
|
|
3838
|
-
|
|
3837
|
+
let viem;
|
|
3838
|
+
try {
|
|
3839
|
+
viem = await import("viem");
|
|
3840
|
+
} catch {
|
|
3841
|
+
throw new UserInputValidationError(
|
|
3842
|
+
"`viem` is required for signTransaction. Install it and try again."
|
|
3843
|
+
);
|
|
3844
|
+
}
|
|
3845
|
+
const serialized = viem.serializeTransaction(transaction);
|
|
3839
3846
|
const response = await sign(id, { data: serialized });
|
|
3840
|
-
const signature2 = parseSignature(response.signature);
|
|
3841
|
-
const signedTransaction = serializeTransaction(
|
|
3847
|
+
const signature2 = viem.parseSignature(response.signature);
|
|
3848
|
+
const signedTransaction = viem.serializeTransaction(
|
|
3842
3849
|
transaction,
|
|
3843
3850
|
signature2
|
|
3844
3851
|
);
|
|
3845
3852
|
return signedTransaction;
|
|
3846
3853
|
},
|
|
3847
3854
|
async signTypedData(parameters) {
|
|
3855
|
+
let viem;
|
|
3856
|
+
try {
|
|
3857
|
+
viem = await import("viem");
|
|
3858
|
+
} catch {
|
|
3859
|
+
throw new UserInputValidationError(
|
|
3860
|
+
"`viem` is required for signTypedData. Install it and try again."
|
|
3861
|
+
);
|
|
3862
|
+
}
|
|
3848
3863
|
const {
|
|
3849
3864
|
domain = {},
|
|
3850
3865
|
message,
|
|
3851
3866
|
primaryType
|
|
3852
3867
|
} = parameters;
|
|
3853
3868
|
const types = {
|
|
3854
|
-
EIP712Domain: getTypesForEIP712Domain({ domain }),
|
|
3869
|
+
EIP712Domain: viem.getTypesForEIP712Domain({ domain }),
|
|
3855
3870
|
...parameters.types
|
|
3856
3871
|
};
|
|
3857
3872
|
const openApiMessage = {
|
|
@@ -3860,9 +3875,9 @@ function toEvmAccount(data) {
|
|
|
3860
3875
|
primaryType,
|
|
3861
3876
|
message
|
|
3862
3877
|
};
|
|
3863
|
-
const hash = hashTypedData(openApiMessage);
|
|
3878
|
+
const hash = viem.hashTypedData(openApiMessage);
|
|
3864
3879
|
const result = await sign(id, { data: hash });
|
|
3865
|
-
return result.signature;
|
|
3880
|
+
return normalizeSignature(result.signature);
|
|
3866
3881
|
}
|
|
3867
3882
|
};
|
|
3868
3883
|
return account;
|
|
@@ -3962,6 +3977,12 @@ var EvmClient = class {
|
|
|
3962
3977
|
}
|
|
3963
3978
|
throw new AccountNotFoundError();
|
|
3964
3979
|
}
|
|
3980
|
+
/**
|
|
3981
|
+
* Retrieves delegated accounts linked to an EVM address on a specific chain.
|
|
3982
|
+
*
|
|
3983
|
+
* @param options - Options containing the address and chain ID
|
|
3984
|
+
* @returns List of linked accounts
|
|
3985
|
+
*/
|
|
3965
3986
|
async getLinkedAccounts(options) {
|
|
3966
3987
|
const response = await getAccountsV2({
|
|
3967
3988
|
address: options.address,
|
|
@@ -4098,8 +4119,201 @@ var EvmClient = class {
|
|
|
4098
4119
|
EvmClient.type = "evmWallet";
|
|
4099
4120
|
|
|
4100
4121
|
// src/wallets/solana/solanaClient.ts
|
|
4122
|
+
import { createPrivateKey, createPublicKey } from "crypto";
|
|
4101
4123
|
import bs58 from "bs58";
|
|
4102
4124
|
|
|
4125
|
+
// src/wallets/solana/actions/constants.ts
|
|
4126
|
+
var USDC_MAINNET_MINT_ADDRESS = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
4127
|
+
var USDC_DEVNET_MINT_ADDRESS = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU";
|
|
4128
|
+
var DEFAULT_COMPUTE_UNIT_LIMIT = 2e5;
|
|
4129
|
+
var DEFAULT_COMPUTE_UNIT_PRICE = 50000n;
|
|
4130
|
+
|
|
4131
|
+
// src/wallets/solana/actions/utils.ts
|
|
4132
|
+
function getUsdcMintAddress(cluster) {
|
|
4133
|
+
if (cluster === "mainnet-beta") {
|
|
4134
|
+
return USDC_MAINNET_MINT_ADDRESS;
|
|
4135
|
+
}
|
|
4136
|
+
return USDC_DEVNET_MINT_ADDRESS;
|
|
4137
|
+
}
|
|
4138
|
+
function getRpcEndpoint(cluster) {
|
|
4139
|
+
return cluster === "mainnet-beta" ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com";
|
|
4140
|
+
}
|
|
4141
|
+
function getWsEndpoint(cluster) {
|
|
4142
|
+
return cluster === "mainnet-beta" ? "wss://api.mainnet-beta.solana.com" : "wss://api.devnet.solana.com";
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
// src/wallets/solana/actions/sendTransaction.ts
|
|
4146
|
+
async function sendTransaction(options) {
|
|
4147
|
+
const {
|
|
4148
|
+
account,
|
|
4149
|
+
cluster,
|
|
4150
|
+
instructions,
|
|
4151
|
+
computeUnitLimit,
|
|
4152
|
+
computeUnitPrice,
|
|
4153
|
+
rpcUrl,
|
|
4154
|
+
wsUrl
|
|
4155
|
+
} = options;
|
|
4156
|
+
let solanaKit;
|
|
4157
|
+
let computeBudget;
|
|
4158
|
+
let transactionConfirmation;
|
|
4159
|
+
let koraModule;
|
|
4160
|
+
try {
|
|
4161
|
+
solanaKit = await import("@solana/kit");
|
|
4162
|
+
} catch {
|
|
4163
|
+
throw new UserInputValidationError(
|
|
4164
|
+
"`@solana/kit` is required for sendTransaction. Install it and try again."
|
|
4165
|
+
);
|
|
4166
|
+
}
|
|
4167
|
+
try {
|
|
4168
|
+
computeBudget = await import("@solana-program/compute-budget");
|
|
4169
|
+
} catch {
|
|
4170
|
+
throw new UserInputValidationError(
|
|
4171
|
+
"`@solana-program/compute-budget` is required for sendTransaction. Install it and try again."
|
|
4172
|
+
);
|
|
4173
|
+
}
|
|
4174
|
+
try {
|
|
4175
|
+
koraModule = await import("@solana/kora");
|
|
4176
|
+
} catch {
|
|
4177
|
+
throw new UserInputValidationError(
|
|
4178
|
+
"`@solana/kora` is required for sendTransaction. Install it and try again."
|
|
4179
|
+
);
|
|
4180
|
+
}
|
|
4181
|
+
try {
|
|
4182
|
+
transactionConfirmation = await import("@solana/transaction-confirmation");
|
|
4183
|
+
} catch {
|
|
4184
|
+
throw new UserInputValidationError(
|
|
4185
|
+
"`@solana/transaction-confirmation` is required for sendTransaction. Install it and try again."
|
|
4186
|
+
);
|
|
4187
|
+
}
|
|
4188
|
+
const userAddress = solanaKit.address(account.address);
|
|
4189
|
+
const clientConfig2 = getConfig();
|
|
4190
|
+
if (!clientConfig2?.publishableKey) {
|
|
4191
|
+
throw new MissingPublishableKeyError("sendTransaction");
|
|
4192
|
+
}
|
|
4193
|
+
const basePath = clientConfig2.basePath || "https://api.openfort.io";
|
|
4194
|
+
const client = new koraModule.KoraClient({
|
|
4195
|
+
rpcUrl: `${basePath}/rpc/solana/${cluster}`,
|
|
4196
|
+
apiKey: `Bearer ${clientConfig2.publishableKey}`
|
|
4197
|
+
});
|
|
4198
|
+
const rpc = solanaKit.createSolanaRpc(rpcUrl ?? getRpcEndpoint(cluster));
|
|
4199
|
+
const rpcSubscriptions = solanaKit.createSolanaRpcSubscriptions(
|
|
4200
|
+
wsUrl ?? getWsEndpoint(cluster)
|
|
4201
|
+
);
|
|
4202
|
+
const confirmTransaction = transactionConfirmation.createRecentSignatureConfirmationPromiseFactory({
|
|
4203
|
+
rpc,
|
|
4204
|
+
rpcSubscriptions
|
|
4205
|
+
});
|
|
4206
|
+
const { signer_address } = await client.getPayerSigner();
|
|
4207
|
+
const blockhashResponse = await client.getBlockhash();
|
|
4208
|
+
let txMsg = solanaKit.pipe(
|
|
4209
|
+
solanaKit.createTransactionMessage({ version: 0 }),
|
|
4210
|
+
(tx) => solanaKit.setTransactionMessageFeePayer(
|
|
4211
|
+
solanaKit.address(signer_address),
|
|
4212
|
+
tx
|
|
4213
|
+
),
|
|
4214
|
+
// Kora's getBlockhash does not return lastValidBlockHeight, so we use 0n.
|
|
4215
|
+
// Transaction expiry is handled by the confirmTransaction timeout instead.
|
|
4216
|
+
(tx) => solanaKit.setTransactionMessageLifetimeUsingBlockhash(
|
|
4217
|
+
{
|
|
4218
|
+
blockhash: blockhashResponse.blockhash,
|
|
4219
|
+
lastValidBlockHeight: 0n
|
|
4220
|
+
},
|
|
4221
|
+
tx
|
|
4222
|
+
),
|
|
4223
|
+
(tx) => solanaKit.appendTransactionMessageInstructions(instructions, tx),
|
|
4224
|
+
(tx) => computeBudget.updateOrAppendSetComputeUnitPriceInstruction(
|
|
4225
|
+
computeUnitPrice ?? DEFAULT_COMPUTE_UNIT_PRICE,
|
|
4226
|
+
tx
|
|
4227
|
+
),
|
|
4228
|
+
(tx) => computeBudget.updateOrAppendSetComputeUnitLimitInstruction(
|
|
4229
|
+
computeUnitLimit ?? DEFAULT_COMPUTE_UNIT_LIMIT,
|
|
4230
|
+
tx
|
|
4231
|
+
)
|
|
4232
|
+
);
|
|
4233
|
+
if (computeUnitLimit === void 0) {
|
|
4234
|
+
const estimateComputeUnitLimit = computeBudget.estimateComputeUnitLimitFactory({ rpc });
|
|
4235
|
+
try {
|
|
4236
|
+
const estimatedLimit = await estimateComputeUnitLimit(txMsg);
|
|
4237
|
+
txMsg = computeBudget.updateOrAppendSetComputeUnitLimitInstruction(
|
|
4238
|
+
estimatedLimit,
|
|
4239
|
+
txMsg
|
|
4240
|
+
);
|
|
4241
|
+
} catch {
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
const compiled = solanaKit.compileTransaction(txMsg);
|
|
4245
|
+
const messageBase64 = Buffer.from(
|
|
4246
|
+
compiled.messageBytes
|
|
4247
|
+
).toString("base64");
|
|
4248
|
+
const signatureHex = await account.signTransaction({
|
|
4249
|
+
transaction: messageBase64
|
|
4250
|
+
});
|
|
4251
|
+
const sigBytes = new Uint8Array(
|
|
4252
|
+
Buffer.from(signatureHex.replace(/^0x/, ""), "hex")
|
|
4253
|
+
);
|
|
4254
|
+
const EMPTY_SIGNATURE = new Uint8Array(64);
|
|
4255
|
+
const signatures = Object.fromEntries(
|
|
4256
|
+
Object.entries(compiled.signatures).map(([addr]) => [
|
|
4257
|
+
addr,
|
|
4258
|
+
addr === userAddress ? sigBytes : EMPTY_SIGNATURE
|
|
4259
|
+
])
|
|
4260
|
+
);
|
|
4261
|
+
const signed = { ...compiled, signatures };
|
|
4262
|
+
const base64Full = solanaKit.getBase64EncodedWireTransaction(signed);
|
|
4263
|
+
const { signed_transaction } = await client.signTransaction({
|
|
4264
|
+
transaction: base64Full,
|
|
4265
|
+
signer_key: signer_address
|
|
4266
|
+
});
|
|
4267
|
+
const signature2 = await rpc.sendTransaction(
|
|
4268
|
+
signed_transaction,
|
|
4269
|
+
{ encoding: "base64" }
|
|
4270
|
+
).send();
|
|
4271
|
+
await confirmTransaction({
|
|
4272
|
+
commitment: "confirmed",
|
|
4273
|
+
signature: signature2,
|
|
4274
|
+
abortSignal: AbortSignal.timeout(6e4)
|
|
4275
|
+
});
|
|
4276
|
+
return { signature: signature2 };
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
// src/wallets/solana/actions/sendRawTransaction.ts
|
|
4280
|
+
async function sendRawTransaction(options) {
|
|
4281
|
+
const {
|
|
4282
|
+
account,
|
|
4283
|
+
cluster,
|
|
4284
|
+
transaction,
|
|
4285
|
+
computeUnitLimit,
|
|
4286
|
+
computeUnitPrice,
|
|
4287
|
+
rpcUrl,
|
|
4288
|
+
wsUrl
|
|
4289
|
+
} = options;
|
|
4290
|
+
let solanaKit;
|
|
4291
|
+
try {
|
|
4292
|
+
solanaKit = await import("@solana/kit");
|
|
4293
|
+
} catch {
|
|
4294
|
+
throw new UserInputValidationError(
|
|
4295
|
+
"`@solana/kit` is required for sendRawTransaction. Install it and try again."
|
|
4296
|
+
);
|
|
4297
|
+
}
|
|
4298
|
+
const txBytes = new Uint8Array(Buffer.from(transaction, "base64"));
|
|
4299
|
+
const decoded = solanaKit.getTransactionDecoder().decode(txBytes);
|
|
4300
|
+
const compiledMessage = solanaKit.getCompiledTransactionMessageDecoder().decode(decoded.messageBytes);
|
|
4301
|
+
const rpc = solanaKit.createSolanaRpc(rpcUrl ?? getRpcEndpoint(cluster));
|
|
4302
|
+
const decompiled = await solanaKit.decompileTransactionMessageFetchingLookupTables(
|
|
4303
|
+
compiledMessage,
|
|
4304
|
+
rpc
|
|
4305
|
+
);
|
|
4306
|
+
return sendTransaction({
|
|
4307
|
+
account,
|
|
4308
|
+
cluster,
|
|
4309
|
+
instructions: [...decompiled.instructions],
|
|
4310
|
+
computeUnitLimit,
|
|
4311
|
+
computeUnitPrice,
|
|
4312
|
+
rpcUrl,
|
|
4313
|
+
wsUrl
|
|
4314
|
+
});
|
|
4315
|
+
}
|
|
4316
|
+
|
|
4103
4317
|
// src/wallets/solana/actions/signMessage.ts
|
|
4104
4318
|
async function signMessage(options) {
|
|
4105
4319
|
const { accountId, message } = options;
|
|
@@ -4122,6 +4336,150 @@ async function signTransaction(options) {
|
|
|
4122
4336
|
};
|
|
4123
4337
|
}
|
|
4124
4338
|
|
|
4339
|
+
// src/wallets/solana/actions/rpc.ts
|
|
4340
|
+
async function createRpcClient(cluster, rpcUrl) {
|
|
4341
|
+
let solanaKit;
|
|
4342
|
+
try {
|
|
4343
|
+
solanaKit = await import("@solana/kit");
|
|
4344
|
+
} catch {
|
|
4345
|
+
throw new UserInputValidationError(
|
|
4346
|
+
"`@solana/kit` is required. Install it and try again."
|
|
4347
|
+
);
|
|
4348
|
+
}
|
|
4349
|
+
return solanaKit.createSolanaRpc(rpcUrl ?? getRpcEndpoint(cluster));
|
|
4350
|
+
}
|
|
4351
|
+
|
|
4352
|
+
// src/wallets/solana/actions/transfer.ts
|
|
4353
|
+
async function transfer(options) {
|
|
4354
|
+
const { account, cluster, rpcUrl, ...rest } = options;
|
|
4355
|
+
const rpc = await createRpcClient(cluster, rpcUrl);
|
|
4356
|
+
const instructions = !options.token || options.token.toLowerCase() === "sol" ? await getNativeTransferInstructions({
|
|
4357
|
+
from: account.address,
|
|
4358
|
+
to: options.to,
|
|
4359
|
+
amount: options.amount
|
|
4360
|
+
}) : await getSplTransferInstructions({
|
|
4361
|
+
rpc,
|
|
4362
|
+
from: account.address,
|
|
4363
|
+
to: options.to,
|
|
4364
|
+
mintAddress: options.token.toLowerCase() === "usdc" ? getUsdcMintAddress(cluster) : options.token,
|
|
4365
|
+
amount: options.amount
|
|
4366
|
+
});
|
|
4367
|
+
return sendTransaction({
|
|
4368
|
+
account,
|
|
4369
|
+
cluster,
|
|
4370
|
+
instructions,
|
|
4371
|
+
rpcUrl,
|
|
4372
|
+
computeUnitLimit: rest.computeUnitLimit,
|
|
4373
|
+
computeUnitPrice: rest.computeUnitPrice,
|
|
4374
|
+
wsUrl: rest.wsUrl
|
|
4375
|
+
});
|
|
4376
|
+
}
|
|
4377
|
+
async function getNativeTransferInstructions({
|
|
4378
|
+
from,
|
|
4379
|
+
to,
|
|
4380
|
+
amount
|
|
4381
|
+
}) {
|
|
4382
|
+
let solanaKit;
|
|
4383
|
+
let systemProgram;
|
|
4384
|
+
try {
|
|
4385
|
+
solanaKit = await import("@solana/kit");
|
|
4386
|
+
} catch {
|
|
4387
|
+
throw new UserInputValidationError(
|
|
4388
|
+
"`@solana/kit` is required for transfer. Install it and try again."
|
|
4389
|
+
);
|
|
4390
|
+
}
|
|
4391
|
+
try {
|
|
4392
|
+
systemProgram = await import("@solana-program/system");
|
|
4393
|
+
} catch {
|
|
4394
|
+
throw new UserInputValidationError(
|
|
4395
|
+
"`@solana-program/system` is required for SOL transfers. Install it and try again."
|
|
4396
|
+
);
|
|
4397
|
+
}
|
|
4398
|
+
const fromAddr = solanaKit.address(from);
|
|
4399
|
+
const toAddr = solanaKit.address(to);
|
|
4400
|
+
return [
|
|
4401
|
+
systemProgram.getTransferSolInstruction({
|
|
4402
|
+
source: solanaKit.createNoopSigner(fromAddr),
|
|
4403
|
+
destination: toAddr,
|
|
4404
|
+
amount
|
|
4405
|
+
})
|
|
4406
|
+
];
|
|
4407
|
+
}
|
|
4408
|
+
async function getSplTransferInstructions({
|
|
4409
|
+
rpc,
|
|
4410
|
+
from,
|
|
4411
|
+
to,
|
|
4412
|
+
mintAddress,
|
|
4413
|
+
amount
|
|
4414
|
+
}) {
|
|
4415
|
+
let solanaKit;
|
|
4416
|
+
let tokenProgram;
|
|
4417
|
+
try {
|
|
4418
|
+
solanaKit = await import("@solana/kit");
|
|
4419
|
+
} catch {
|
|
4420
|
+
throw new UserInputValidationError(
|
|
4421
|
+
"`@solana/kit` is required for transfer. Install it and try again."
|
|
4422
|
+
);
|
|
4423
|
+
}
|
|
4424
|
+
try {
|
|
4425
|
+
tokenProgram = await import("@solana-program/token");
|
|
4426
|
+
} catch {
|
|
4427
|
+
throw new UserInputValidationError(
|
|
4428
|
+
"`@solana-program/token` is required for SPL transfers. Install it and try again."
|
|
4429
|
+
);
|
|
4430
|
+
}
|
|
4431
|
+
const fromAddr = solanaKit.address(from);
|
|
4432
|
+
const toAddr = solanaKit.address(to);
|
|
4433
|
+
const mintAddr = solanaKit.address(mintAddress);
|
|
4434
|
+
const mintInfo = await tokenProgram.fetchMint(rpc, mintAddr).catch(() => {
|
|
4435
|
+
throw new UserInputValidationError(
|
|
4436
|
+
`Failed to fetch mint account for ${mintAddress}. Verify the mint address is correct.`
|
|
4437
|
+
);
|
|
4438
|
+
});
|
|
4439
|
+
const [sourceAta] = await tokenProgram.findAssociatedTokenPda({
|
|
4440
|
+
mint: mintAddr,
|
|
4441
|
+
owner: fromAddr,
|
|
4442
|
+
tokenProgram: tokenProgram.TOKEN_PROGRAM_ADDRESS
|
|
4443
|
+
});
|
|
4444
|
+
const [destAta] = await tokenProgram.findAssociatedTokenPda({
|
|
4445
|
+
mint: mintAddr,
|
|
4446
|
+
owner: toAddr,
|
|
4447
|
+
tokenProgram: tokenProgram.TOKEN_PROGRAM_ADDRESS
|
|
4448
|
+
});
|
|
4449
|
+
const sourceAcct = await tokenProgram.fetchToken(rpc, sourceAta).catch(() => {
|
|
4450
|
+
throw new UserInputValidationError(
|
|
4451
|
+
`Source account has no token account for mint ${mintAddress}`
|
|
4452
|
+
);
|
|
4453
|
+
});
|
|
4454
|
+
if (sourceAcct.data.amount < amount) {
|
|
4455
|
+
throw new UserInputValidationError(
|
|
4456
|
+
`Insufficient token balance: have ${sourceAcct.data.amount}, need ${amount}`
|
|
4457
|
+
);
|
|
4458
|
+
}
|
|
4459
|
+
const instructions = [];
|
|
4460
|
+
const destAccountInfo = await rpc.getAccountInfo(destAta, { encoding: "base64" }).send();
|
|
4461
|
+
if (!destAccountInfo.value) {
|
|
4462
|
+
const createDestIx = await tokenProgram.getCreateAssociatedTokenInstructionAsync({
|
|
4463
|
+
payer: solanaKit.createNoopSigner(fromAddr),
|
|
4464
|
+
owner: toAddr,
|
|
4465
|
+
ata: destAta,
|
|
4466
|
+
mint: mintAddr
|
|
4467
|
+
});
|
|
4468
|
+
instructions.push(createDestIx);
|
|
4469
|
+
}
|
|
4470
|
+
instructions.push(
|
|
4471
|
+
tokenProgram.getTransferCheckedInstruction({
|
|
4472
|
+
source: sourceAta,
|
|
4473
|
+
mint: mintAddr,
|
|
4474
|
+
destination: destAta,
|
|
4475
|
+
authority: solanaKit.createNoopSigner(fromAddr),
|
|
4476
|
+
amount,
|
|
4477
|
+
decimals: mintInfo.data.decimals
|
|
4478
|
+
})
|
|
4479
|
+
);
|
|
4480
|
+
return instructions;
|
|
4481
|
+
}
|
|
4482
|
+
|
|
4125
4483
|
// src/wallets/solana/accounts/solanaAccount.ts
|
|
4126
4484
|
function toSolanaAccount(data) {
|
|
4127
4485
|
const { id, address } = data;
|
|
@@ -4142,6 +4500,12 @@ function toSolanaAccount(data) {
|
|
|
4142
4500
|
transaction: parameters.transaction
|
|
4143
4501
|
});
|
|
4144
4502
|
return result.signedTransaction;
|
|
4503
|
+
},
|
|
4504
|
+
async transfer(options) {
|
|
4505
|
+
return transfer({ ...options, account });
|
|
4506
|
+
},
|
|
4507
|
+
async sendRawTransaction(options) {
|
|
4508
|
+
return sendRawTransaction({ ...options, account });
|
|
4145
4509
|
}
|
|
4146
4510
|
};
|
|
4147
4511
|
return account;
|
|
@@ -4298,9 +4662,24 @@ var SolanaClient = class {
|
|
|
4298
4662
|
);
|
|
4299
4663
|
}
|
|
4300
4664
|
}
|
|
4301
|
-
if (privateKeyBytes.length ===
|
|
4302
|
-
|
|
4303
|
-
|
|
4665
|
+
if (privateKeyBytes.length === 32) {
|
|
4666
|
+
const edPrivKey = createPrivateKey({
|
|
4667
|
+
key: Buffer.concat([
|
|
4668
|
+
Buffer.from(
|
|
4669
|
+
// PKCS#8 DER prefix for Ed25519 (RFC 8410): 16 bytes wrapping a 32-byte seed
|
|
4670
|
+
"302e020100300506032b657004220420",
|
|
4671
|
+
"hex"
|
|
4672
|
+
),
|
|
4673
|
+
privateKeyBytes
|
|
4674
|
+
]),
|
|
4675
|
+
format: "der",
|
|
4676
|
+
type: "pkcs8"
|
|
4677
|
+
});
|
|
4678
|
+
const rawPublicKey = createPublicKey(edPrivKey).export({ type: "spki", format: "der" }).subarray(-32);
|
|
4679
|
+
privateKeyBytes = new Uint8Array(
|
|
4680
|
+
Buffer.concat([privateKeyBytes, rawPublicKey])
|
|
4681
|
+
);
|
|
4682
|
+
} else if (privateKeyBytes.length !== 64) {
|
|
4304
4683
|
throw new UserInputValidationError(
|
|
4305
4684
|
"Private key must be 32 bytes (seed) or 64 bytes (full keypair)"
|
|
4306
4685
|
);
|
|
@@ -4372,16 +4751,12 @@ var SolanaClient = class {
|
|
|
4372
4751
|
return response.signature;
|
|
4373
4752
|
}
|
|
4374
4753
|
};
|
|
4754
|
+
/** Wallet type identifier used for client registration */
|
|
4375
4755
|
SolanaClient.type = "solanaWallet";
|
|
4376
4756
|
|
|
4377
4757
|
// src/index.ts
|
|
4378
4758
|
import { ShieldAuthProvider as ShieldAuthProvider2 } from "@openfort/shield-js";
|
|
4379
4759
|
|
|
4380
|
-
// src/wallets/evm/actions/sendTransaction.ts
|
|
4381
|
-
import { createPublicClient, getAddress, http } from "viem";
|
|
4382
|
-
import * as chains from "viem/chains";
|
|
4383
|
-
import { hashAuthorization } from "viem/utils";
|
|
4384
|
-
|
|
4385
4760
|
// src/wallets/evm/actions/updateToDelegated.ts
|
|
4386
4761
|
async function update(options) {
|
|
4387
4762
|
const { chainId, walletId, implementationType, accountId } = options;
|
|
@@ -4396,11 +4771,37 @@ async function update(options) {
|
|
|
4396
4771
|
}
|
|
4397
4772
|
|
|
4398
4773
|
// src/wallets/evm/actions/sendTransaction.ts
|
|
4399
|
-
async function
|
|
4774
|
+
async function sendTransaction2(options) {
|
|
4775
|
+
let viem;
|
|
4776
|
+
let viemChains;
|
|
4777
|
+
let viemUtils;
|
|
4778
|
+
try {
|
|
4779
|
+
viem = await import("viem");
|
|
4780
|
+
} catch {
|
|
4781
|
+
throw new UserInputValidationError(
|
|
4782
|
+
"`viem` is required for sendTransaction. Install it and try again."
|
|
4783
|
+
);
|
|
4784
|
+
}
|
|
4785
|
+
try {
|
|
4786
|
+
viemChains = await import("viem/chains");
|
|
4787
|
+
} catch {
|
|
4788
|
+
throw new UserInputValidationError(
|
|
4789
|
+
"`viem` is required for sendTransaction. Install it and try again."
|
|
4790
|
+
);
|
|
4791
|
+
}
|
|
4792
|
+
try {
|
|
4793
|
+
viemUtils = await import("viem/utils");
|
|
4794
|
+
} catch {
|
|
4795
|
+
throw new UserInputValidationError(
|
|
4796
|
+
"`viem` is required for sendTransaction. Install it and try again."
|
|
4797
|
+
);
|
|
4798
|
+
}
|
|
4400
4799
|
const { account, chainId, interactions, policy, rpcUrl } = options;
|
|
4401
|
-
const transport = rpcUrl ? http(rpcUrl) : http();
|
|
4402
|
-
const allChains = Object.values(
|
|
4403
|
-
const chain = allChains.find(
|
|
4800
|
+
const transport = rpcUrl ? viem.http(rpcUrl) : viem.http();
|
|
4801
|
+
const allChains = Object.values(viemChains);
|
|
4802
|
+
const chain = allChains.find(
|
|
4803
|
+
(c) => typeof c === "object" && c !== null && "id" in c && c.id === chainId
|
|
4804
|
+
);
|
|
4404
4805
|
if (!chain) {
|
|
4405
4806
|
throw new DelegationError(
|
|
4406
4807
|
`Unknown chain ID ${chainId}. Provide a custom rpcUrl for unsupported chains.`
|
|
@@ -4409,7 +4810,7 @@ async function sendTransaction(options) {
|
|
|
4409
4810
|
let signedAuthorization;
|
|
4410
4811
|
let txAccountId;
|
|
4411
4812
|
const response = await getAccountsV2({
|
|
4412
|
-
address: getAddress(account.address),
|
|
4813
|
+
address: viem.getAddress(account.address),
|
|
4413
4814
|
accountType: "Delegated Account",
|
|
4414
4815
|
chainType: "EVM",
|
|
4415
4816
|
chainId
|
|
@@ -4423,11 +4824,11 @@ async function sendTransaction(options) {
|
|
|
4423
4824
|
});
|
|
4424
4825
|
txAccountId = updated.id;
|
|
4425
4826
|
const implementationAddress = "0x000000009b1d0af20d8c6d0a44e162d11f9b8f00";
|
|
4426
|
-
const publicClient = createPublicClient({ chain, transport });
|
|
4827
|
+
const publicClient = viem.createPublicClient({ chain, transport });
|
|
4427
4828
|
const eoaNonce = await publicClient.getTransactionCount({
|
|
4428
4829
|
address: account.address
|
|
4429
4830
|
});
|
|
4430
|
-
const authHash = hashAuthorization({
|
|
4831
|
+
const authHash = viemUtils.hashAuthorization({
|
|
4431
4832
|
contractAddress: implementationAddress,
|
|
4432
4833
|
chainId,
|
|
4433
4834
|
nonce: eoaNonce
|
|
@@ -4454,19 +4855,6 @@ async function sendTransaction(options) {
|
|
|
4454
4855
|
});
|
|
4455
4856
|
}
|
|
4456
4857
|
|
|
4457
|
-
// src/wallets/evm/actions/signMessage.ts
|
|
4458
|
-
import { toHex, toPrefixedMessage as toPrefixedMessage2 } from "viem";
|
|
4459
|
-
|
|
4460
|
-
// src/wallets/evm/actions/signTransaction.ts
|
|
4461
|
-
import {
|
|
4462
|
-
keccak256,
|
|
4463
|
-
parseSignature as parseSignature2,
|
|
4464
|
-
serializeTransaction as serializeTransaction2
|
|
4465
|
-
} from "viem";
|
|
4466
|
-
|
|
4467
|
-
// src/wallets/evm/actions/signTypedData.ts
|
|
4468
|
-
import { hashTypedData as hashTypedData2 } from "viem";
|
|
4469
|
-
|
|
4470
4858
|
// src/policies/evmSchema.ts
|
|
4471
4859
|
import { z } from "zod";
|
|
4472
4860
|
var EthValueOperatorEnum = z.enum(["<=", ">=", "<", ">"]);
|
|
@@ -4869,7 +5257,7 @@ var Openfort = class {
|
|
|
4869
5257
|
/** Update EOA to delegated account */
|
|
4870
5258
|
update,
|
|
4871
5259
|
/** Delegate + create + sign + submit a gasless transaction in one call */
|
|
4872
|
-
sendTransaction
|
|
5260
|
+
sendTransaction: sendTransaction2
|
|
4873
5261
|
},
|
|
4874
5262
|
/** Embedded wallet operations (User custody) */
|
|
4875
5263
|
embedded: {
|
|
@@ -4898,7 +5286,13 @@ var Openfort = class {
|
|
|
4898
5286
|
/** Import private key (with E2E encryption) */
|
|
4899
5287
|
import: solanaClient.importAccount.bind(solanaClient),
|
|
4900
5288
|
/** Export private key (with E2E encryption) */
|
|
4901
|
-
export: solanaClient.exportAccount.bind(solanaClient)
|
|
5289
|
+
export: solanaClient.exportAccount.bind(solanaClient),
|
|
5290
|
+
/** Send a gasless transaction via Kora */
|
|
5291
|
+
sendTransaction,
|
|
5292
|
+
/** Send a pre-built base64 transaction via Kora gasless flow */
|
|
5293
|
+
sendRawTransaction,
|
|
5294
|
+
/** Transfer SOL or SPL tokens (high-level) */
|
|
5295
|
+
transfer
|
|
4902
5296
|
},
|
|
4903
5297
|
/** Embedded wallet operations (User custody) */
|
|
4904
5298
|
embedded: {
|