@openfort/openfort-js 0.8.12 → 0.8.13
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/dist/index.cjs +465 -12
- package/dist/index.d.ts +5 -1
- package/dist/index.js +465 -12
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4256,6 +4256,7 @@ class DeviceCredentialsManager {
|
|
|
4256
4256
|
}
|
|
4257
4257
|
}
|
|
4258
4258
|
|
|
4259
|
+
/* eslint-disable */
|
|
4259
4260
|
const isBrowser = () => typeof document !== 'undefined';
|
|
4260
4261
|
|
|
4261
4262
|
function base64URLEncode(str) {
|
|
@@ -4770,7 +4771,7 @@ class JsonRpcError extends Error {
|
|
|
4770
4771
|
}
|
|
4771
4772
|
}
|
|
4772
4773
|
|
|
4773
|
-
const buildOpenfortTransactions = async (transactionRequest, backendApiClients, account, authentication, policyId) => {
|
|
4774
|
+
const buildOpenfortTransactions$4 = async (transactionRequest, backendApiClients, account, authentication, policyId) => {
|
|
4774
4775
|
const interactions = transactionRequest.map((tx) => {
|
|
4775
4776
|
if (!tx.to) {
|
|
4776
4777
|
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'eth_sendTransaction requires a "to" field');
|
|
@@ -4801,7 +4802,7 @@ const buildOpenfortTransactions = async (transactionRequest, backendApiClients,
|
|
|
4801
4802
|
return transactionResponse.data;
|
|
4802
4803
|
};
|
|
4803
4804
|
const sendTransaction = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
4804
|
-
const openfortTransaction = await buildOpenfortTransactions(params, backendClient, account, authentication, policyId);
|
|
4805
|
+
const openfortTransaction = await buildOpenfortTransactions$4(params, backendClient, account, authentication, policyId);
|
|
4805
4806
|
let response;
|
|
4806
4807
|
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
4807
4808
|
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
@@ -5998,6 +5999,29 @@ const soneiumMinato = {
|
|
|
5998
5999
|
slug: 'soneium-minato-testnet',
|
|
5999
6000
|
};
|
|
6000
6001
|
|
|
6002
|
+
const sophonTestnet = {
|
|
6003
|
+
name: 'Sophon Testnet',
|
|
6004
|
+
title: 'Sophon Testnet',
|
|
6005
|
+
chain: 'sophon-testnet',
|
|
6006
|
+
rpc: ['https://rpc.testnet.sophon.xyz'],
|
|
6007
|
+
nativeCurrency: {
|
|
6008
|
+
name: 'Sophon',
|
|
6009
|
+
symbol: 'SOPH',
|
|
6010
|
+
decimals: 18,
|
|
6011
|
+
},
|
|
6012
|
+
shortName: 'sophon-testnet',
|
|
6013
|
+
chainId: 531050104,
|
|
6014
|
+
explorers: [
|
|
6015
|
+
{
|
|
6016
|
+
name: 'Sophon Block Explorer',
|
|
6017
|
+
url: 'https://explorer.testnet.sophon.xyz',
|
|
6018
|
+
standard: 'EIP3091',
|
|
6019
|
+
},
|
|
6020
|
+
],
|
|
6021
|
+
testnet: true,
|
|
6022
|
+
slug: 'sophon-testnet',
|
|
6023
|
+
};
|
|
6024
|
+
|
|
6001
6025
|
const chainMap = {
|
|
6002
6026
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6003
6027
|
56: chain$m,
|
|
@@ -6055,6 +6079,342 @@ const chainMap = {
|
|
|
6055
6079
|
5611: opBNBTestnet,
|
|
6056
6080
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6057
6081
|
1946: soneiumMinato,
|
|
6082
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6083
|
+
531050104: sophonTestnet,
|
|
6084
|
+
};
|
|
6085
|
+
|
|
6086
|
+
const REQUIRED_CHAIN_PROPERTIES = ['chainId', 'chainName', 'nativeCurrency'];
|
|
6087
|
+
const isValidChainParameter = (chainParam) => (REQUIRED_CHAIN_PROPERTIES.every((key) => key in chainParam));
|
|
6088
|
+
const validateNativeCurrency = (nativeCurrency) => {
|
|
6089
|
+
if (!nativeCurrency || typeof nativeCurrency !== 'object')
|
|
6090
|
+
return false;
|
|
6091
|
+
const hasRequiredProperties = ('name' in nativeCurrency
|
|
6092
|
+
&& 'symbol' in nativeCurrency
|
|
6093
|
+
&& 'decimals' in nativeCurrency);
|
|
6094
|
+
if (!hasRequiredProperties)
|
|
6095
|
+
return false;
|
|
6096
|
+
return (typeof nativeCurrency.name === 'string'
|
|
6097
|
+
&& typeof nativeCurrency.symbol === 'string'
|
|
6098
|
+
&& typeof nativeCurrency.decimals === 'number'
|
|
6099
|
+
&& Number.isInteger(nativeCurrency.decimals));
|
|
6100
|
+
};
|
|
6101
|
+
const transformChainParameter = (chainParam) => {
|
|
6102
|
+
if (!chainParam || typeof chainParam !== 'object') {
|
|
6103
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid chain parameter: expected an object');
|
|
6104
|
+
}
|
|
6105
|
+
if (!isValidChainParameter(chainParam)) {
|
|
6106
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid chain parameter. The following properties are required: ${REQUIRED_CHAIN_PROPERTIES.join(', ')}`);
|
|
6107
|
+
}
|
|
6108
|
+
if (!chainParam.chainName || chainParam.chainName.trim() === '') {
|
|
6109
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'chainName cannot be empty');
|
|
6110
|
+
}
|
|
6111
|
+
if (!validateNativeCurrency(chainParam.nativeCurrency)) {
|
|
6112
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid nativeCurrency object');
|
|
6113
|
+
}
|
|
6114
|
+
if (chainParam.rpcUrls?.length === 0) {
|
|
6115
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'At least one RPC URL must be provided');
|
|
6116
|
+
}
|
|
6117
|
+
// Ensure chainId is a valid hex string
|
|
6118
|
+
if (!/^0x[0-9a-fA-F]+$/.test(chainParam.chainId)) {
|
|
6119
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'chainId must be a valid hex string');
|
|
6120
|
+
}
|
|
6121
|
+
return {
|
|
6122
|
+
chainId: chainParam.chainId,
|
|
6123
|
+
blockExplorerUrls: chainParam.blockExplorerUrls || [],
|
|
6124
|
+
chainName: chainParam.chainName,
|
|
6125
|
+
iconUrls: chainParam.iconUrls || [],
|
|
6126
|
+
rpcUrls: chainParam.rpcUrls || [],
|
|
6127
|
+
nativeCurrency: chainParam.nativeCurrency,
|
|
6128
|
+
};
|
|
6129
|
+
};
|
|
6130
|
+
const addEthereumChain = async ({ params, rpcProvider, }) => {
|
|
6131
|
+
if (!params || !Array.isArray(params) || params.length === 0) {
|
|
6132
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid parameters for wallet_addEthereumChain');
|
|
6133
|
+
}
|
|
6134
|
+
const chainParameter = transformChainParameter(params[0]);
|
|
6135
|
+
const chainIdNumber = parseInt(chainParameter.chainId, 16);
|
|
6136
|
+
// Get current chainId
|
|
6137
|
+
const { chainId: currentChainId } = await rpcProvider.detectNetwork();
|
|
6138
|
+
// If we're already on this chain, return false
|
|
6139
|
+
if (chainIdNumber === currentChainId) {
|
|
6140
|
+
return false;
|
|
6141
|
+
}
|
|
6142
|
+
try {
|
|
6143
|
+
const signer = await SignerManager.embedded();
|
|
6144
|
+
if (!signer) {
|
|
6145
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - no account available');
|
|
6146
|
+
}
|
|
6147
|
+
// If we successfully configured the chain, return null (success)
|
|
6148
|
+
return null;
|
|
6149
|
+
}
|
|
6150
|
+
catch (error) {
|
|
6151
|
+
if (error instanceof Error) {
|
|
6152
|
+
throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Failed to add chain: ${error.message}`);
|
|
6153
|
+
}
|
|
6154
|
+
throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Failed to add chain');
|
|
6155
|
+
}
|
|
6156
|
+
};
|
|
6157
|
+
|
|
6158
|
+
function formatPolicyData(policy) {
|
|
6159
|
+
const data = (() => {
|
|
6160
|
+
if (policy.type === 'token-allowance') {
|
|
6161
|
+
return {
|
|
6162
|
+
allowance: (policy.data.allowance.toString()),
|
|
6163
|
+
};
|
|
6164
|
+
}
|
|
6165
|
+
if (policy.type === 'gas-limit') {
|
|
6166
|
+
return {
|
|
6167
|
+
limit: policy.data.limit.toString(),
|
|
6168
|
+
};
|
|
6169
|
+
}
|
|
6170
|
+
return policy.data;
|
|
6171
|
+
})();
|
|
6172
|
+
return {
|
|
6173
|
+
data,
|
|
6174
|
+
type: typeof policy.type === 'string' ? policy.type : policy.type.custom,
|
|
6175
|
+
};
|
|
6176
|
+
}
|
|
6177
|
+
function formatPermissionRequest(permission) {
|
|
6178
|
+
return {
|
|
6179
|
+
...permission,
|
|
6180
|
+
policies: permission.policies.map(formatPolicyData),
|
|
6181
|
+
required: permission.required ?? false,
|
|
6182
|
+
type: typeof permission.type === 'string'
|
|
6183
|
+
? permission.type
|
|
6184
|
+
: permission.type.custom,
|
|
6185
|
+
};
|
|
6186
|
+
}
|
|
6187
|
+
const formatSessionRequest$1 = (address, chainId, validAfter, validUntil, policyId, optimistic = false, whitelist, player, limit, externalOwnerAddress) => {
|
|
6188
|
+
const request = {
|
|
6189
|
+
address,
|
|
6190
|
+
chainId,
|
|
6191
|
+
validAfter,
|
|
6192
|
+
validUntil,
|
|
6193
|
+
optimistic,
|
|
6194
|
+
whitelist,
|
|
6195
|
+
player,
|
|
6196
|
+
};
|
|
6197
|
+
if (policyId)
|
|
6198
|
+
request.policy = policyId;
|
|
6199
|
+
if (externalOwnerAddress)
|
|
6200
|
+
request.externalOwnerAddress = externalOwnerAddress;
|
|
6201
|
+
if (limit)
|
|
6202
|
+
request.limit = limit;
|
|
6203
|
+
return request;
|
|
6204
|
+
};
|
|
6205
|
+
const buildOpenfortTransactions$3 = async (params, backendApiClients, account, authentication, policyId) => {
|
|
6206
|
+
const param = params[0];
|
|
6207
|
+
const now = Math.floor(new Date().getTime() / 1000);
|
|
6208
|
+
const expiry = Math.floor(new Date(Date.now() + param.expiry * 1000).getTime() / 1000);
|
|
6209
|
+
const formattedPermissions = param.permissions.map(formatPermissionRequest);
|
|
6210
|
+
const whitelist = formattedPermissions.filter((p) => p.type === 'contract-call'
|
|
6211
|
+
|| p.type === 'erc20-token-transfer').map((p) => p.data.address);
|
|
6212
|
+
if (param.signer && param.signer.type === 'keys') {
|
|
6213
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
|
|
6214
|
+
}
|
|
6215
|
+
const sessionAddress = param.signer?.data?.id;
|
|
6216
|
+
if (!sessionAddress) {
|
|
6217
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
|
|
6218
|
+
}
|
|
6219
|
+
const sessionRequest = formatSessionRequest$1(sessionAddress, account.chainId, now, expiry, policyId, false, whitelist, authentication.player);
|
|
6220
|
+
const transactionResponse = await backendApiClients.sessionsApi.createSession({
|
|
6221
|
+
createSessionRequest: sessionRequest,
|
|
6222
|
+
}, {
|
|
6223
|
+
headers: {
|
|
6224
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6225
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6226
|
+
'x-player-token': authentication.token,
|
|
6227
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6228
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6229
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6230
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6231
|
+
},
|
|
6232
|
+
});
|
|
6233
|
+
return transactionResponse.data;
|
|
6234
|
+
};
|
|
6235
|
+
function formatRequest(result) {
|
|
6236
|
+
return {
|
|
6237
|
+
expiry: result.validUntil ? Number(result.validUntil) : 0,
|
|
6238
|
+
grantedPermissions: result.whitelist?.map((address) => ({
|
|
6239
|
+
type: 'contract-call',
|
|
6240
|
+
data: {
|
|
6241
|
+
address,
|
|
6242
|
+
calls: [],
|
|
6243
|
+
},
|
|
6244
|
+
policies: [{
|
|
6245
|
+
data: {
|
|
6246
|
+
limit: result.limit,
|
|
6247
|
+
},
|
|
6248
|
+
type: { custom: 'usage-limit' },
|
|
6249
|
+
}],
|
|
6250
|
+
})),
|
|
6251
|
+
permissionsContext: result.id,
|
|
6252
|
+
};
|
|
6253
|
+
}
|
|
6254
|
+
const registerSession = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
6255
|
+
const openfortTransaction = await buildOpenfortTransactions$3(params, backendClient, account, authentication, policyId);
|
|
6256
|
+
let response;
|
|
6257
|
+
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
6258
|
+
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
6259
|
+
const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
|
|
6260
|
+
id: openfortTransaction.id,
|
|
6261
|
+
signatureRequest: { signature },
|
|
6262
|
+
});
|
|
6263
|
+
if (!openfortSignatureResponse) {
|
|
6264
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6265
|
+
}
|
|
6266
|
+
response = openfortSignatureResponse.data;
|
|
6267
|
+
}
|
|
6268
|
+
else {
|
|
6269
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6270
|
+
}
|
|
6271
|
+
if (response.isActive === false) {
|
|
6272
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Failed to request permissions');
|
|
6273
|
+
}
|
|
6274
|
+
return formatRequest(response);
|
|
6275
|
+
};
|
|
6276
|
+
|
|
6277
|
+
const formatSessionRequest = (address, chainId, player, policyId) => {
|
|
6278
|
+
const request = {
|
|
6279
|
+
address,
|
|
6280
|
+
chainId,
|
|
6281
|
+
player,
|
|
6282
|
+
};
|
|
6283
|
+
if (policyId)
|
|
6284
|
+
request.policy = policyId;
|
|
6285
|
+
return request;
|
|
6286
|
+
};
|
|
6287
|
+
const buildOpenfortTransactions$2 = async (params, backendApiClients, account, authentication, policyId) => {
|
|
6288
|
+
const sessionRequest = formatSessionRequest(params.permissionContext, account.chainId, authentication.player, policyId);
|
|
6289
|
+
const transactionResponse = await backendApiClients.sessionsApi.revokeSession({
|
|
6290
|
+
revokeSessionRequest: sessionRequest,
|
|
6291
|
+
}, {
|
|
6292
|
+
headers: {
|
|
6293
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6294
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6295
|
+
'x-player-token': authentication.token,
|
|
6296
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6297
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6298
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6299
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6300
|
+
},
|
|
6301
|
+
});
|
|
6302
|
+
return transactionResponse.data;
|
|
6303
|
+
};
|
|
6304
|
+
const revokeSession = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
6305
|
+
const openfortTransaction = await buildOpenfortTransactions$2(params, backendClient, account, authentication, policyId);
|
|
6306
|
+
let response;
|
|
6307
|
+
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
6308
|
+
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
6309
|
+
const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
|
|
6310
|
+
id: openfortTransaction.id,
|
|
6311
|
+
signatureRequest: { signature },
|
|
6312
|
+
});
|
|
6313
|
+
if (!openfortSignatureResponse) {
|
|
6314
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6315
|
+
}
|
|
6316
|
+
response = openfortSignatureResponse.data;
|
|
6317
|
+
}
|
|
6318
|
+
else {
|
|
6319
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6320
|
+
}
|
|
6321
|
+
if (response.isActive === false) {
|
|
6322
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Failed to request permissions');
|
|
6323
|
+
}
|
|
6324
|
+
return {};
|
|
6325
|
+
};
|
|
6326
|
+
|
|
6327
|
+
const buildOpenfortTransactions$1 = async (calls, backendApiClients, account, authentication, policyId) => {
|
|
6328
|
+
const interactions = calls.map((call) => {
|
|
6329
|
+
if (!call.to) {
|
|
6330
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'wallet_sendCalls requires a "to" field');
|
|
6331
|
+
}
|
|
6332
|
+
return {
|
|
6333
|
+
to: String(call.to),
|
|
6334
|
+
data: call.data ? String(call.data) : undefined,
|
|
6335
|
+
value: call.value ? String(call.value) : undefined,
|
|
6336
|
+
};
|
|
6337
|
+
});
|
|
6338
|
+
const transactionResponse = await backendApiClients.transactionIntentsApi.createTransactionIntent({
|
|
6339
|
+
createTransactionIntentRequest: {
|
|
6340
|
+
policy: policyId,
|
|
6341
|
+
chainId: account.chainId,
|
|
6342
|
+
interactions,
|
|
6343
|
+
},
|
|
6344
|
+
}, {
|
|
6345
|
+
headers: {
|
|
6346
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6347
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6348
|
+
'x-player-token': authentication.token,
|
|
6349
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6350
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6351
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6352
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6353
|
+
},
|
|
6354
|
+
});
|
|
6355
|
+
return transactionResponse.data;
|
|
6356
|
+
};
|
|
6357
|
+
const sendCalls = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
6358
|
+
const openfortTransaction = await buildOpenfortTransactions$1(params[0].calls, backendClient, account, authentication, policyId);
|
|
6359
|
+
let response;
|
|
6360
|
+
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
6361
|
+
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
6362
|
+
const openfortSignatureResponse = (await backendClient.transactionIntentsApi.signature({
|
|
6363
|
+
id: openfortTransaction.id,
|
|
6364
|
+
signatureRequest: { signature },
|
|
6365
|
+
})).data.response;
|
|
6366
|
+
if (!openfortSignatureResponse) {
|
|
6367
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6368
|
+
}
|
|
6369
|
+
response = openfortSignatureResponse;
|
|
6370
|
+
}
|
|
6371
|
+
else if (openfortTransaction.response) {
|
|
6372
|
+
response = openfortTransaction.response;
|
|
6373
|
+
}
|
|
6374
|
+
else {
|
|
6375
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6376
|
+
}
|
|
6377
|
+
if (response.status === 0 && !response.transactionHash) {
|
|
6378
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, response.error.reason);
|
|
6379
|
+
}
|
|
6380
|
+
return response.transactionHash;
|
|
6381
|
+
};
|
|
6382
|
+
|
|
6383
|
+
const buildOpenfortTransactions = async (transactionIntentId, backendApiClients, authentication) => {
|
|
6384
|
+
const transactionResponse = await backendApiClients.transactionIntentsApi.getTransactionIntent({
|
|
6385
|
+
id: transactionIntentId,
|
|
6386
|
+
}, {
|
|
6387
|
+
headers: {
|
|
6388
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6389
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6390
|
+
'x-player-token': authentication.token,
|
|
6391
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6392
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6393
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6394
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6395
|
+
},
|
|
6396
|
+
});
|
|
6397
|
+
return transactionResponse.data;
|
|
6398
|
+
};
|
|
6399
|
+
const getCallStatus = async ({ params, authentication, backendClient, }) => {
|
|
6400
|
+
const transactionIntent = await buildOpenfortTransactions(params[0], backendClient, authentication);
|
|
6401
|
+
return {
|
|
6402
|
+
status: !transactionIntent.response ? 'PENDING' : 'CONFIRMED',
|
|
6403
|
+
receipts: transactionIntent.response
|
|
6404
|
+
? [{
|
|
6405
|
+
status: transactionIntent.response.status === 0 ? 'reverted' : 'success',
|
|
6406
|
+
logs: transactionIntent.response.logs?.map((log) => ({
|
|
6407
|
+
address: log.address,
|
|
6408
|
+
data: log.data,
|
|
6409
|
+
topics: log.topics,
|
|
6410
|
+
})) || [],
|
|
6411
|
+
blockHash: transactionIntent.response.transactionHash || '',
|
|
6412
|
+
blockNumber: BigInt(transactionIntent.response.blockNumber || 0),
|
|
6413
|
+
gasUsed: BigInt(transactionIntent.response.gasUsed || 0),
|
|
6414
|
+
transactionHash: transactionIntent.response.transactionHash || '',
|
|
6415
|
+
}]
|
|
6416
|
+
: undefined,
|
|
6417
|
+
};
|
|
6058
6418
|
};
|
|
6059
6419
|
|
|
6060
6420
|
class EvmProvider {
|
|
@@ -6089,7 +6449,10 @@ class EvmProvider {
|
|
|
6089
6449
|
};
|
|
6090
6450
|
async #performRequest(request) {
|
|
6091
6451
|
switch (request.method) {
|
|
6092
|
-
case 'eth_accounts':
|
|
6452
|
+
case 'eth_accounts': {
|
|
6453
|
+
const account = Account.fromStorage(this.#storage);
|
|
6454
|
+
return account ? [account.address] : [];
|
|
6455
|
+
}
|
|
6093
6456
|
case 'eth_requestAccounts': {
|
|
6094
6457
|
let account = Account.fromStorage(this.#storage);
|
|
6095
6458
|
if (account) {
|
|
@@ -6148,6 +6511,96 @@ class EvmProvider {
|
|
|
6148
6511
|
const { chainId } = await this.#rpcProvider.detectNetwork();
|
|
6149
6512
|
return bytes.hexlify(chainId);
|
|
6150
6513
|
}
|
|
6514
|
+
case 'wallet_addEthereumChain': {
|
|
6515
|
+
const signer = SignerManager.fromStorage();
|
|
6516
|
+
if (!signer) {
|
|
6517
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - must be authenticated and configured with a signer');
|
|
6518
|
+
}
|
|
6519
|
+
return await addEthereumChain({
|
|
6520
|
+
params: request.params || [],
|
|
6521
|
+
rpcProvider: this.#rpcProvider,
|
|
6522
|
+
});
|
|
6523
|
+
}
|
|
6524
|
+
// EIP-5792: Wallet Call API
|
|
6525
|
+
case 'wallet_showCallsStatus': {
|
|
6526
|
+
return null;
|
|
6527
|
+
}
|
|
6528
|
+
case 'wallet_getCallsStatus': {
|
|
6529
|
+
const account = Account.fromStorage(this.#storage);
|
|
6530
|
+
const signer = SignerManager.fromStorage();
|
|
6531
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6532
|
+
if (!account || !signer || !authentication) {
|
|
6533
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6534
|
+
}
|
|
6535
|
+
return await getCallStatus({
|
|
6536
|
+
params: (request.params || {}),
|
|
6537
|
+
authentication,
|
|
6538
|
+
backendClient: this.#backendApiClients,
|
|
6539
|
+
account,
|
|
6540
|
+
});
|
|
6541
|
+
}
|
|
6542
|
+
case 'wallet_sendCalls': {
|
|
6543
|
+
const account = Account.fromStorage(this.#storage);
|
|
6544
|
+
const signer = SignerManager.fromStorage();
|
|
6545
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6546
|
+
if (!account || !signer || !authentication) {
|
|
6547
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6548
|
+
}
|
|
6549
|
+
return await sendCalls({
|
|
6550
|
+
params: request.params || [],
|
|
6551
|
+
signer,
|
|
6552
|
+
account,
|
|
6553
|
+
authentication,
|
|
6554
|
+
backendClient: this.#backendApiClients,
|
|
6555
|
+
policyId: this.#policyId,
|
|
6556
|
+
});
|
|
6557
|
+
}
|
|
6558
|
+
case 'wallet_grantPermissions': {
|
|
6559
|
+
const account = Account.fromStorage(this.#storage);
|
|
6560
|
+
const signer = SignerManager.fromStorage();
|
|
6561
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6562
|
+
if (!account || !signer || !authentication) {
|
|
6563
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6564
|
+
}
|
|
6565
|
+
return await registerSession({
|
|
6566
|
+
params: (request.params || []),
|
|
6567
|
+
signer,
|
|
6568
|
+
account,
|
|
6569
|
+
authentication,
|
|
6570
|
+
backendClient: this.#backendApiClients,
|
|
6571
|
+
policyId: this.#policyId,
|
|
6572
|
+
});
|
|
6573
|
+
}
|
|
6574
|
+
// EIP-7715: Wallet Session Key API
|
|
6575
|
+
case 'wallet_revokePermissions': {
|
|
6576
|
+
const account = Account.fromStorage(this.#storage);
|
|
6577
|
+
const signer = SignerManager.fromStorage();
|
|
6578
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6579
|
+
if (!account || !signer || !authentication) {
|
|
6580
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6581
|
+
}
|
|
6582
|
+
return await revokeSession({
|
|
6583
|
+
params: (request.params || {}),
|
|
6584
|
+
signer,
|
|
6585
|
+
account,
|
|
6586
|
+
authentication,
|
|
6587
|
+
backendClient: this.#backendApiClients,
|
|
6588
|
+
});
|
|
6589
|
+
}
|
|
6590
|
+
case 'wallet_getCapabilities': {
|
|
6591
|
+
const { chainId } = await this.#rpcProvider.detectNetwork();
|
|
6592
|
+
const capabilities = {
|
|
6593
|
+
[bytes.hexlify(chainId)]: {
|
|
6594
|
+
permissions: {
|
|
6595
|
+
supported: true,
|
|
6596
|
+
signerTypes: ['account', 'key'],
|
|
6597
|
+
keyTypes: ['secp256k1'],
|
|
6598
|
+
permissionTypes: ['contract-calls'],
|
|
6599
|
+
},
|
|
6600
|
+
},
|
|
6601
|
+
};
|
|
6602
|
+
return capabilities;
|
|
6603
|
+
}
|
|
6151
6604
|
// Pass through methods
|
|
6152
6605
|
case 'eth_gasPrice':
|
|
6153
6606
|
case 'eth_getBalance':
|
|
@@ -6164,7 +6617,7 @@ class EvmProvider {
|
|
|
6164
6617
|
return this.#rpcProvider.send(request.method, request.params || []);
|
|
6165
6618
|
}
|
|
6166
6619
|
default: {
|
|
6167
|
-
throw new JsonRpcError(ProviderErrorCode.UNSUPPORTED_METHOD,
|
|
6620
|
+
throw new JsonRpcError(ProviderErrorCode.UNSUPPORTED_METHOD, `${request.method}: Method not supported`);
|
|
6168
6621
|
}
|
|
6169
6622
|
}
|
|
6170
6623
|
}
|
|
@@ -6308,7 +6761,7 @@ class Openfort {
|
|
|
6308
6761
|
* @returns A Provider instance.
|
|
6309
6762
|
* @throws {OpenfortError} If the signer is not an EmbeddedSigner.
|
|
6310
6763
|
*/
|
|
6311
|
-
getEthereumProvider(options = {
|
|
6764
|
+
getEthereumProvider(options = {}) {
|
|
6312
6765
|
const authentication = Authentication.fromStorage(this.storage);
|
|
6313
6766
|
const signer = SignerManager.fromStorage();
|
|
6314
6767
|
const account = Account.fromStorage(this.storage);
|
|
@@ -6321,12 +6774,10 @@ class Openfort {
|
|
|
6321
6774
|
backendApiClients: this.backendApiClients,
|
|
6322
6775
|
policyId: options.policy,
|
|
6323
6776
|
});
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
});
|
|
6329
|
-
}
|
|
6777
|
+
announceProvider({
|
|
6778
|
+
info: { ...openfortProviderInfo, ...options.providerInfo },
|
|
6779
|
+
provider,
|
|
6780
|
+
});
|
|
6330
6781
|
return provider;
|
|
6331
6782
|
}
|
|
6332
6783
|
/**
|
|
@@ -6406,7 +6857,9 @@ class Openfort {
|
|
|
6406
6857
|
// eslint-disable-next-line no-param-reassign
|
|
6407
6858
|
delete types.EIP712Domain;
|
|
6408
6859
|
const account = Account.fromStorage(this.storage);
|
|
6409
|
-
if (account &&
|
|
6860
|
+
if (account && [AccountType.UPGRADEABLE_V5,
|
|
6861
|
+
AccountType.UPGRADEABLE_V6,
|
|
6862
|
+
AccountType.ZKSYNC_UPGRADEABLE_V1].includes(account.type)) {
|
|
6410
6863
|
const updatedDomain = {
|
|
6411
6864
|
name: 'Openfort',
|
|
6412
6865
|
version: '0.5',
|
package/dist/index.d.ts
CHANGED
|
@@ -589,8 +589,12 @@ declare class Openfort {
|
|
|
589
589
|
* @throws {OpenfortError} If the signer is not an EmbeddedSigner.
|
|
590
590
|
*/
|
|
591
591
|
getEthereumProvider(options?: {
|
|
592
|
-
announceProvider: boolean;
|
|
593
592
|
policy?: string;
|
|
593
|
+
providerInfo?: {
|
|
594
|
+
icon: `data:image/${string}`;
|
|
595
|
+
name: string;
|
|
596
|
+
rdns: string;
|
|
597
|
+
};
|
|
594
598
|
}): Provider;
|
|
595
599
|
/**
|
|
596
600
|
* Configures a session key and returns the session key details.
|
package/dist/index.js
CHANGED
|
@@ -4233,6 +4233,7 @@ class DeviceCredentialsManager {
|
|
|
4233
4233
|
}
|
|
4234
4234
|
}
|
|
4235
4235
|
|
|
4236
|
+
/* eslint-disable */
|
|
4236
4237
|
const isBrowser = () => typeof document !== 'undefined';
|
|
4237
4238
|
|
|
4238
4239
|
function base64URLEncode(str) {
|
|
@@ -4747,7 +4748,7 @@ class JsonRpcError extends Error {
|
|
|
4747
4748
|
}
|
|
4748
4749
|
}
|
|
4749
4750
|
|
|
4750
|
-
const buildOpenfortTransactions = async (transactionRequest, backendApiClients, account, authentication, policyId) => {
|
|
4751
|
+
const buildOpenfortTransactions$4 = async (transactionRequest, backendApiClients, account, authentication, policyId) => {
|
|
4751
4752
|
const interactions = transactionRequest.map((tx) => {
|
|
4752
4753
|
if (!tx.to) {
|
|
4753
4754
|
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'eth_sendTransaction requires a "to" field');
|
|
@@ -4778,7 +4779,7 @@ const buildOpenfortTransactions = async (transactionRequest, backendApiClients,
|
|
|
4778
4779
|
return transactionResponse.data;
|
|
4779
4780
|
};
|
|
4780
4781
|
const sendTransaction = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
4781
|
-
const openfortTransaction = await buildOpenfortTransactions(params, backendClient, account, authentication, policyId);
|
|
4782
|
+
const openfortTransaction = await buildOpenfortTransactions$4(params, backendClient, account, authentication, policyId);
|
|
4782
4783
|
let response;
|
|
4783
4784
|
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
4784
4785
|
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
@@ -5975,6 +5976,29 @@ const soneiumMinato = {
|
|
|
5975
5976
|
slug: 'soneium-minato-testnet',
|
|
5976
5977
|
};
|
|
5977
5978
|
|
|
5979
|
+
const sophonTestnet = {
|
|
5980
|
+
name: 'Sophon Testnet',
|
|
5981
|
+
title: 'Sophon Testnet',
|
|
5982
|
+
chain: 'sophon-testnet',
|
|
5983
|
+
rpc: ['https://rpc.testnet.sophon.xyz'],
|
|
5984
|
+
nativeCurrency: {
|
|
5985
|
+
name: 'Sophon',
|
|
5986
|
+
symbol: 'SOPH',
|
|
5987
|
+
decimals: 18,
|
|
5988
|
+
},
|
|
5989
|
+
shortName: 'sophon-testnet',
|
|
5990
|
+
chainId: 531050104,
|
|
5991
|
+
explorers: [
|
|
5992
|
+
{
|
|
5993
|
+
name: 'Sophon Block Explorer',
|
|
5994
|
+
url: 'https://explorer.testnet.sophon.xyz',
|
|
5995
|
+
standard: 'EIP3091',
|
|
5996
|
+
},
|
|
5997
|
+
],
|
|
5998
|
+
testnet: true,
|
|
5999
|
+
slug: 'sophon-testnet',
|
|
6000
|
+
};
|
|
6001
|
+
|
|
5978
6002
|
const chainMap = {
|
|
5979
6003
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
5980
6004
|
56: chain$m,
|
|
@@ -6032,6 +6056,342 @@ const chainMap = {
|
|
|
6032
6056
|
5611: opBNBTestnet,
|
|
6033
6057
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6034
6058
|
1946: soneiumMinato,
|
|
6059
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6060
|
+
531050104: sophonTestnet,
|
|
6061
|
+
};
|
|
6062
|
+
|
|
6063
|
+
const REQUIRED_CHAIN_PROPERTIES = ['chainId', 'chainName', 'nativeCurrency'];
|
|
6064
|
+
const isValidChainParameter = (chainParam) => (REQUIRED_CHAIN_PROPERTIES.every((key) => key in chainParam));
|
|
6065
|
+
const validateNativeCurrency = (nativeCurrency) => {
|
|
6066
|
+
if (!nativeCurrency || typeof nativeCurrency !== 'object')
|
|
6067
|
+
return false;
|
|
6068
|
+
const hasRequiredProperties = ('name' in nativeCurrency
|
|
6069
|
+
&& 'symbol' in nativeCurrency
|
|
6070
|
+
&& 'decimals' in nativeCurrency);
|
|
6071
|
+
if (!hasRequiredProperties)
|
|
6072
|
+
return false;
|
|
6073
|
+
return (typeof nativeCurrency.name === 'string'
|
|
6074
|
+
&& typeof nativeCurrency.symbol === 'string'
|
|
6075
|
+
&& typeof nativeCurrency.decimals === 'number'
|
|
6076
|
+
&& Number.isInteger(nativeCurrency.decimals));
|
|
6077
|
+
};
|
|
6078
|
+
const transformChainParameter = (chainParam) => {
|
|
6079
|
+
if (!chainParam || typeof chainParam !== 'object') {
|
|
6080
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid chain parameter: expected an object');
|
|
6081
|
+
}
|
|
6082
|
+
if (!isValidChainParameter(chainParam)) {
|
|
6083
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid chain parameter. The following properties are required: ${REQUIRED_CHAIN_PROPERTIES.join(', ')}`);
|
|
6084
|
+
}
|
|
6085
|
+
if (!chainParam.chainName || chainParam.chainName.trim() === '') {
|
|
6086
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'chainName cannot be empty');
|
|
6087
|
+
}
|
|
6088
|
+
if (!validateNativeCurrency(chainParam.nativeCurrency)) {
|
|
6089
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid nativeCurrency object');
|
|
6090
|
+
}
|
|
6091
|
+
if (chainParam.rpcUrls?.length === 0) {
|
|
6092
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'At least one RPC URL must be provided');
|
|
6093
|
+
}
|
|
6094
|
+
// Ensure chainId is a valid hex string
|
|
6095
|
+
if (!/^0x[0-9a-fA-F]+$/.test(chainParam.chainId)) {
|
|
6096
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'chainId must be a valid hex string');
|
|
6097
|
+
}
|
|
6098
|
+
return {
|
|
6099
|
+
chainId: chainParam.chainId,
|
|
6100
|
+
blockExplorerUrls: chainParam.blockExplorerUrls || [],
|
|
6101
|
+
chainName: chainParam.chainName,
|
|
6102
|
+
iconUrls: chainParam.iconUrls || [],
|
|
6103
|
+
rpcUrls: chainParam.rpcUrls || [],
|
|
6104
|
+
nativeCurrency: chainParam.nativeCurrency,
|
|
6105
|
+
};
|
|
6106
|
+
};
|
|
6107
|
+
const addEthereumChain = async ({ params, rpcProvider, }) => {
|
|
6108
|
+
if (!params || !Array.isArray(params) || params.length === 0) {
|
|
6109
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Invalid parameters for wallet_addEthereumChain');
|
|
6110
|
+
}
|
|
6111
|
+
const chainParameter = transformChainParameter(params[0]);
|
|
6112
|
+
const chainIdNumber = parseInt(chainParameter.chainId, 16);
|
|
6113
|
+
// Get current chainId
|
|
6114
|
+
const { chainId: currentChainId } = await rpcProvider.detectNetwork();
|
|
6115
|
+
// If we're already on this chain, return false
|
|
6116
|
+
if (chainIdNumber === currentChainId) {
|
|
6117
|
+
return false;
|
|
6118
|
+
}
|
|
6119
|
+
try {
|
|
6120
|
+
const signer = await SignerManager.embedded();
|
|
6121
|
+
if (!signer) {
|
|
6122
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - no account available');
|
|
6123
|
+
}
|
|
6124
|
+
// If we successfully configured the chain, return null (success)
|
|
6125
|
+
return null;
|
|
6126
|
+
}
|
|
6127
|
+
catch (error) {
|
|
6128
|
+
if (error instanceof Error) {
|
|
6129
|
+
throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Failed to add chain: ${error.message}`);
|
|
6130
|
+
}
|
|
6131
|
+
throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Failed to add chain');
|
|
6132
|
+
}
|
|
6133
|
+
};
|
|
6134
|
+
|
|
6135
|
+
function formatPolicyData(policy) {
|
|
6136
|
+
const data = (() => {
|
|
6137
|
+
if (policy.type === 'token-allowance') {
|
|
6138
|
+
return {
|
|
6139
|
+
allowance: (policy.data.allowance.toString()),
|
|
6140
|
+
};
|
|
6141
|
+
}
|
|
6142
|
+
if (policy.type === 'gas-limit') {
|
|
6143
|
+
return {
|
|
6144
|
+
limit: policy.data.limit.toString(),
|
|
6145
|
+
};
|
|
6146
|
+
}
|
|
6147
|
+
return policy.data;
|
|
6148
|
+
})();
|
|
6149
|
+
return {
|
|
6150
|
+
data,
|
|
6151
|
+
type: typeof policy.type === 'string' ? policy.type : policy.type.custom,
|
|
6152
|
+
};
|
|
6153
|
+
}
|
|
6154
|
+
function formatPermissionRequest(permission) {
|
|
6155
|
+
return {
|
|
6156
|
+
...permission,
|
|
6157
|
+
policies: permission.policies.map(formatPolicyData),
|
|
6158
|
+
required: permission.required ?? false,
|
|
6159
|
+
type: typeof permission.type === 'string'
|
|
6160
|
+
? permission.type
|
|
6161
|
+
: permission.type.custom,
|
|
6162
|
+
};
|
|
6163
|
+
}
|
|
6164
|
+
const formatSessionRequest$1 = (address, chainId, validAfter, validUntil, policyId, optimistic = false, whitelist, player, limit, externalOwnerAddress) => {
|
|
6165
|
+
const request = {
|
|
6166
|
+
address,
|
|
6167
|
+
chainId,
|
|
6168
|
+
validAfter,
|
|
6169
|
+
validUntil,
|
|
6170
|
+
optimistic,
|
|
6171
|
+
whitelist,
|
|
6172
|
+
player,
|
|
6173
|
+
};
|
|
6174
|
+
if (policyId)
|
|
6175
|
+
request.policy = policyId;
|
|
6176
|
+
if (externalOwnerAddress)
|
|
6177
|
+
request.externalOwnerAddress = externalOwnerAddress;
|
|
6178
|
+
if (limit)
|
|
6179
|
+
request.limit = limit;
|
|
6180
|
+
return request;
|
|
6181
|
+
};
|
|
6182
|
+
const buildOpenfortTransactions$3 = async (params, backendApiClients, account, authentication, policyId) => {
|
|
6183
|
+
const param = params[0];
|
|
6184
|
+
const now = Math.floor(new Date().getTime() / 1000);
|
|
6185
|
+
const expiry = Math.floor(new Date(Date.now() + param.expiry * 1000).getTime() / 1000);
|
|
6186
|
+
const formattedPermissions = param.permissions.map(formatPermissionRequest);
|
|
6187
|
+
const whitelist = formattedPermissions.filter((p) => p.type === 'contract-call'
|
|
6188
|
+
|| p.type === 'erc20-token-transfer').map((p) => p.data.address);
|
|
6189
|
+
if (param.signer && param.signer.type === 'keys') {
|
|
6190
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
|
|
6191
|
+
}
|
|
6192
|
+
const sessionAddress = param.signer?.data?.id;
|
|
6193
|
+
if (!sessionAddress) {
|
|
6194
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'Failed to request permissions - missing session address');
|
|
6195
|
+
}
|
|
6196
|
+
const sessionRequest = formatSessionRequest$1(sessionAddress, account.chainId, now, expiry, policyId, false, whitelist, authentication.player);
|
|
6197
|
+
const transactionResponse = await backendApiClients.sessionsApi.createSession({
|
|
6198
|
+
createSessionRequest: sessionRequest,
|
|
6199
|
+
}, {
|
|
6200
|
+
headers: {
|
|
6201
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6202
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6203
|
+
'x-player-token': authentication.token,
|
|
6204
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6205
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6206
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6207
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6208
|
+
},
|
|
6209
|
+
});
|
|
6210
|
+
return transactionResponse.data;
|
|
6211
|
+
};
|
|
6212
|
+
function formatRequest(result) {
|
|
6213
|
+
return {
|
|
6214
|
+
expiry: result.validUntil ? Number(result.validUntil) : 0,
|
|
6215
|
+
grantedPermissions: result.whitelist?.map((address) => ({
|
|
6216
|
+
type: 'contract-call',
|
|
6217
|
+
data: {
|
|
6218
|
+
address,
|
|
6219
|
+
calls: [],
|
|
6220
|
+
},
|
|
6221
|
+
policies: [{
|
|
6222
|
+
data: {
|
|
6223
|
+
limit: result.limit,
|
|
6224
|
+
},
|
|
6225
|
+
type: { custom: 'usage-limit' },
|
|
6226
|
+
}],
|
|
6227
|
+
})),
|
|
6228
|
+
permissionsContext: result.id,
|
|
6229
|
+
};
|
|
6230
|
+
}
|
|
6231
|
+
const registerSession = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
6232
|
+
const openfortTransaction = await buildOpenfortTransactions$3(params, backendClient, account, authentication, policyId);
|
|
6233
|
+
let response;
|
|
6234
|
+
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
6235
|
+
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
6236
|
+
const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
|
|
6237
|
+
id: openfortTransaction.id,
|
|
6238
|
+
signatureRequest: { signature },
|
|
6239
|
+
});
|
|
6240
|
+
if (!openfortSignatureResponse) {
|
|
6241
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6242
|
+
}
|
|
6243
|
+
response = openfortSignatureResponse.data;
|
|
6244
|
+
}
|
|
6245
|
+
else {
|
|
6246
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6247
|
+
}
|
|
6248
|
+
if (response.isActive === false) {
|
|
6249
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Failed to request permissions');
|
|
6250
|
+
}
|
|
6251
|
+
return formatRequest(response);
|
|
6252
|
+
};
|
|
6253
|
+
|
|
6254
|
+
const formatSessionRequest = (address, chainId, player, policyId) => {
|
|
6255
|
+
const request = {
|
|
6256
|
+
address,
|
|
6257
|
+
chainId,
|
|
6258
|
+
player,
|
|
6259
|
+
};
|
|
6260
|
+
if (policyId)
|
|
6261
|
+
request.policy = policyId;
|
|
6262
|
+
return request;
|
|
6263
|
+
};
|
|
6264
|
+
const buildOpenfortTransactions$2 = async (params, backendApiClients, account, authentication, policyId) => {
|
|
6265
|
+
const sessionRequest = formatSessionRequest(params.permissionContext, account.chainId, authentication.player, policyId);
|
|
6266
|
+
const transactionResponse = await backendApiClients.sessionsApi.revokeSession({
|
|
6267
|
+
revokeSessionRequest: sessionRequest,
|
|
6268
|
+
}, {
|
|
6269
|
+
headers: {
|
|
6270
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6271
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6272
|
+
'x-player-token': authentication.token,
|
|
6273
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6274
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6275
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6276
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6277
|
+
},
|
|
6278
|
+
});
|
|
6279
|
+
return transactionResponse.data;
|
|
6280
|
+
};
|
|
6281
|
+
const revokeSession = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
6282
|
+
const openfortTransaction = await buildOpenfortTransactions$2(params, backendClient, account, authentication, policyId);
|
|
6283
|
+
let response;
|
|
6284
|
+
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
6285
|
+
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
6286
|
+
const openfortSignatureResponse = await backendClient.sessionsApi.signatureSession({
|
|
6287
|
+
id: openfortTransaction.id,
|
|
6288
|
+
signatureRequest: { signature },
|
|
6289
|
+
});
|
|
6290
|
+
if (!openfortSignatureResponse) {
|
|
6291
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6292
|
+
}
|
|
6293
|
+
response = openfortSignatureResponse.data;
|
|
6294
|
+
}
|
|
6295
|
+
else {
|
|
6296
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6297
|
+
}
|
|
6298
|
+
if (response.isActive === false) {
|
|
6299
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Failed to request permissions');
|
|
6300
|
+
}
|
|
6301
|
+
return {};
|
|
6302
|
+
};
|
|
6303
|
+
|
|
6304
|
+
const buildOpenfortTransactions$1 = async (calls, backendApiClients, account, authentication, policyId) => {
|
|
6305
|
+
const interactions = calls.map((call) => {
|
|
6306
|
+
if (!call.to) {
|
|
6307
|
+
throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'wallet_sendCalls requires a "to" field');
|
|
6308
|
+
}
|
|
6309
|
+
return {
|
|
6310
|
+
to: String(call.to),
|
|
6311
|
+
data: call.data ? String(call.data) : undefined,
|
|
6312
|
+
value: call.value ? String(call.value) : undefined,
|
|
6313
|
+
};
|
|
6314
|
+
});
|
|
6315
|
+
const transactionResponse = await backendApiClients.transactionIntentsApi.createTransactionIntent({
|
|
6316
|
+
createTransactionIntentRequest: {
|
|
6317
|
+
policy: policyId,
|
|
6318
|
+
chainId: account.chainId,
|
|
6319
|
+
interactions,
|
|
6320
|
+
},
|
|
6321
|
+
}, {
|
|
6322
|
+
headers: {
|
|
6323
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6324
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6325
|
+
'x-player-token': authentication.token,
|
|
6326
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6327
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6328
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6329
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6330
|
+
},
|
|
6331
|
+
});
|
|
6332
|
+
return transactionResponse.data;
|
|
6333
|
+
};
|
|
6334
|
+
const sendCalls = async ({ params, signer, account, authentication, backendClient, policyId, }) => {
|
|
6335
|
+
const openfortTransaction = await buildOpenfortTransactions$1(params[0].calls, backendClient, account, authentication, policyId);
|
|
6336
|
+
let response;
|
|
6337
|
+
if (openfortTransaction?.nextAction?.payload?.signableHash) {
|
|
6338
|
+
const signature = await signer.sign(openfortTransaction.nextAction.payload.signableHash);
|
|
6339
|
+
const openfortSignatureResponse = (await backendClient.transactionIntentsApi.signature({
|
|
6340
|
+
id: openfortTransaction.id,
|
|
6341
|
+
signatureRequest: { signature },
|
|
6342
|
+
})).data.response;
|
|
6343
|
+
if (!openfortSignatureResponse) {
|
|
6344
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6345
|
+
}
|
|
6346
|
+
response = openfortSignatureResponse;
|
|
6347
|
+
}
|
|
6348
|
+
else if (openfortTransaction.response) {
|
|
6349
|
+
response = openfortTransaction.response;
|
|
6350
|
+
}
|
|
6351
|
+
else {
|
|
6352
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'Transaction failed to submit');
|
|
6353
|
+
}
|
|
6354
|
+
if (response.status === 0 && !response.transactionHash) {
|
|
6355
|
+
throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, response.error.reason);
|
|
6356
|
+
}
|
|
6357
|
+
return response.transactionHash;
|
|
6358
|
+
};
|
|
6359
|
+
|
|
6360
|
+
const buildOpenfortTransactions = async (transactionIntentId, backendApiClients, authentication) => {
|
|
6361
|
+
const transactionResponse = await backendApiClients.transactionIntentsApi.getTransactionIntent({
|
|
6362
|
+
id: transactionIntentId,
|
|
6363
|
+
}, {
|
|
6364
|
+
headers: {
|
|
6365
|
+
authorization: `Bearer ${backendApiClients.config.backend.accessToken}`,
|
|
6366
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6367
|
+
'x-player-token': authentication.token,
|
|
6368
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6369
|
+
'x-auth-provider': authentication.thirdPartyProvider,
|
|
6370
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6371
|
+
'x-token-type': authentication.thirdPartyTokenType,
|
|
6372
|
+
},
|
|
6373
|
+
});
|
|
6374
|
+
return transactionResponse.data;
|
|
6375
|
+
};
|
|
6376
|
+
const getCallStatus = async ({ params, authentication, backendClient, }) => {
|
|
6377
|
+
const transactionIntent = await buildOpenfortTransactions(params[0], backendClient, authentication);
|
|
6378
|
+
return {
|
|
6379
|
+
status: !transactionIntent.response ? 'PENDING' : 'CONFIRMED',
|
|
6380
|
+
receipts: transactionIntent.response
|
|
6381
|
+
? [{
|
|
6382
|
+
status: transactionIntent.response.status === 0 ? 'reverted' : 'success',
|
|
6383
|
+
logs: transactionIntent.response.logs?.map((log) => ({
|
|
6384
|
+
address: log.address,
|
|
6385
|
+
data: log.data,
|
|
6386
|
+
topics: log.topics,
|
|
6387
|
+
})) || [],
|
|
6388
|
+
blockHash: transactionIntent.response.transactionHash || '',
|
|
6389
|
+
blockNumber: BigInt(transactionIntent.response.blockNumber || 0),
|
|
6390
|
+
gasUsed: BigInt(transactionIntent.response.gasUsed || 0),
|
|
6391
|
+
transactionHash: transactionIntent.response.transactionHash || '',
|
|
6392
|
+
}]
|
|
6393
|
+
: undefined,
|
|
6394
|
+
};
|
|
6035
6395
|
};
|
|
6036
6396
|
|
|
6037
6397
|
class EvmProvider {
|
|
@@ -6066,7 +6426,10 @@ class EvmProvider {
|
|
|
6066
6426
|
};
|
|
6067
6427
|
async #performRequest(request) {
|
|
6068
6428
|
switch (request.method) {
|
|
6069
|
-
case 'eth_accounts':
|
|
6429
|
+
case 'eth_accounts': {
|
|
6430
|
+
const account = Account.fromStorage(this.#storage);
|
|
6431
|
+
return account ? [account.address] : [];
|
|
6432
|
+
}
|
|
6070
6433
|
case 'eth_requestAccounts': {
|
|
6071
6434
|
let account = Account.fromStorage(this.#storage);
|
|
6072
6435
|
if (account) {
|
|
@@ -6125,6 +6488,96 @@ class EvmProvider {
|
|
|
6125
6488
|
const { chainId } = await this.#rpcProvider.detectNetwork();
|
|
6126
6489
|
return hexlify(chainId);
|
|
6127
6490
|
}
|
|
6491
|
+
case 'wallet_addEthereumChain': {
|
|
6492
|
+
const signer = SignerManager.fromStorage();
|
|
6493
|
+
if (!signer) {
|
|
6494
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - must be authenticated and configured with a signer');
|
|
6495
|
+
}
|
|
6496
|
+
return await addEthereumChain({
|
|
6497
|
+
params: request.params || [],
|
|
6498
|
+
rpcProvider: this.#rpcProvider,
|
|
6499
|
+
});
|
|
6500
|
+
}
|
|
6501
|
+
// EIP-5792: Wallet Call API
|
|
6502
|
+
case 'wallet_showCallsStatus': {
|
|
6503
|
+
return null;
|
|
6504
|
+
}
|
|
6505
|
+
case 'wallet_getCallsStatus': {
|
|
6506
|
+
const account = Account.fromStorage(this.#storage);
|
|
6507
|
+
const signer = SignerManager.fromStorage();
|
|
6508
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6509
|
+
if (!account || !signer || !authentication) {
|
|
6510
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6511
|
+
}
|
|
6512
|
+
return await getCallStatus({
|
|
6513
|
+
params: (request.params || {}),
|
|
6514
|
+
authentication,
|
|
6515
|
+
backendClient: this.#backendApiClients,
|
|
6516
|
+
account,
|
|
6517
|
+
});
|
|
6518
|
+
}
|
|
6519
|
+
case 'wallet_sendCalls': {
|
|
6520
|
+
const account = Account.fromStorage(this.#storage);
|
|
6521
|
+
const signer = SignerManager.fromStorage();
|
|
6522
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6523
|
+
if (!account || !signer || !authentication) {
|
|
6524
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6525
|
+
}
|
|
6526
|
+
return await sendCalls({
|
|
6527
|
+
params: request.params || [],
|
|
6528
|
+
signer,
|
|
6529
|
+
account,
|
|
6530
|
+
authentication,
|
|
6531
|
+
backendClient: this.#backendApiClients,
|
|
6532
|
+
policyId: this.#policyId,
|
|
6533
|
+
});
|
|
6534
|
+
}
|
|
6535
|
+
case 'wallet_grantPermissions': {
|
|
6536
|
+
const account = Account.fromStorage(this.#storage);
|
|
6537
|
+
const signer = SignerManager.fromStorage();
|
|
6538
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6539
|
+
if (!account || !signer || !authentication) {
|
|
6540
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6541
|
+
}
|
|
6542
|
+
return await registerSession({
|
|
6543
|
+
params: (request.params || []),
|
|
6544
|
+
signer,
|
|
6545
|
+
account,
|
|
6546
|
+
authentication,
|
|
6547
|
+
backendClient: this.#backendApiClients,
|
|
6548
|
+
policyId: this.#policyId,
|
|
6549
|
+
});
|
|
6550
|
+
}
|
|
6551
|
+
// EIP-7715: Wallet Session Key API
|
|
6552
|
+
case 'wallet_revokePermissions': {
|
|
6553
|
+
const account = Account.fromStorage(this.#storage);
|
|
6554
|
+
const signer = SignerManager.fromStorage();
|
|
6555
|
+
const authentication = Authentication.fromStorage(this.#storage);
|
|
6556
|
+
if (!account || !signer || !authentication) {
|
|
6557
|
+
throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorized - call eth_requestAccounts first');
|
|
6558
|
+
}
|
|
6559
|
+
return await revokeSession({
|
|
6560
|
+
params: (request.params || {}),
|
|
6561
|
+
signer,
|
|
6562
|
+
account,
|
|
6563
|
+
authentication,
|
|
6564
|
+
backendClient: this.#backendApiClients,
|
|
6565
|
+
});
|
|
6566
|
+
}
|
|
6567
|
+
case 'wallet_getCapabilities': {
|
|
6568
|
+
const { chainId } = await this.#rpcProvider.detectNetwork();
|
|
6569
|
+
const capabilities = {
|
|
6570
|
+
[hexlify(chainId)]: {
|
|
6571
|
+
permissions: {
|
|
6572
|
+
supported: true,
|
|
6573
|
+
signerTypes: ['account', 'key'],
|
|
6574
|
+
keyTypes: ['secp256k1'],
|
|
6575
|
+
permissionTypes: ['contract-calls'],
|
|
6576
|
+
},
|
|
6577
|
+
},
|
|
6578
|
+
};
|
|
6579
|
+
return capabilities;
|
|
6580
|
+
}
|
|
6128
6581
|
// Pass through methods
|
|
6129
6582
|
case 'eth_gasPrice':
|
|
6130
6583
|
case 'eth_getBalance':
|
|
@@ -6141,7 +6594,7 @@ class EvmProvider {
|
|
|
6141
6594
|
return this.#rpcProvider.send(request.method, request.params || []);
|
|
6142
6595
|
}
|
|
6143
6596
|
default: {
|
|
6144
|
-
throw new JsonRpcError(ProviderErrorCode.UNSUPPORTED_METHOD,
|
|
6597
|
+
throw new JsonRpcError(ProviderErrorCode.UNSUPPORTED_METHOD, `${request.method}: Method not supported`);
|
|
6145
6598
|
}
|
|
6146
6599
|
}
|
|
6147
6600
|
}
|
|
@@ -6285,7 +6738,7 @@ class Openfort {
|
|
|
6285
6738
|
* @returns A Provider instance.
|
|
6286
6739
|
* @throws {OpenfortError} If the signer is not an EmbeddedSigner.
|
|
6287
6740
|
*/
|
|
6288
|
-
getEthereumProvider(options = {
|
|
6741
|
+
getEthereumProvider(options = {}) {
|
|
6289
6742
|
const authentication = Authentication.fromStorage(this.storage);
|
|
6290
6743
|
const signer = SignerManager.fromStorage();
|
|
6291
6744
|
const account = Account.fromStorage(this.storage);
|
|
@@ -6298,12 +6751,10 @@ class Openfort {
|
|
|
6298
6751
|
backendApiClients: this.backendApiClients,
|
|
6299
6752
|
policyId: options.policy,
|
|
6300
6753
|
});
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
});
|
|
6306
|
-
}
|
|
6754
|
+
announceProvider({
|
|
6755
|
+
info: { ...openfortProviderInfo, ...options.providerInfo },
|
|
6756
|
+
provider,
|
|
6757
|
+
});
|
|
6307
6758
|
return provider;
|
|
6308
6759
|
}
|
|
6309
6760
|
/**
|
|
@@ -6383,7 +6834,9 @@ class Openfort {
|
|
|
6383
6834
|
// eslint-disable-next-line no-param-reassign
|
|
6384
6835
|
delete types.EIP712Domain;
|
|
6385
6836
|
const account = Account.fromStorage(this.storage);
|
|
6386
|
-
if (account &&
|
|
6837
|
+
if (account && [AccountType.UPGRADEABLE_V5,
|
|
6838
|
+
AccountType.UPGRADEABLE_V6,
|
|
6839
|
+
AccountType.ZKSYNC_UPGRADEABLE_V1].includes(account.type)) {
|
|
6387
6840
|
const updatedDomain = {
|
|
6388
6841
|
name: 'Openfort',
|
|
6389
6842
|
version: '0.5',
|
package/package.json
CHANGED