kentucky-signer-viem 0.1.3 → 0.1.5
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/README.md +262 -26
- package/dist/index.d.mts +376 -10
- package/dist/index.d.ts +376 -10
- package/dist/index.js +281 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +282 -26
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +465 -3
- package/dist/react/index.d.ts +465 -3
- package/dist/react/index.js +390 -25
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +391 -26
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/account.ts +183 -23
- package/src/client.ts +4 -5
- package/src/index.ts +32 -0
- package/src/intent.ts +167 -0
- package/src/react/index.ts +33 -0
- package/src/react/relayer-hooks.ts +318 -0
- package/src/relayer-client.ts +305 -0
- package/src/secure-client.ts +2 -2
- package/src/types.ts +4 -3
package/dist/react/index.js
CHANGED
|
@@ -21,14 +21,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
KentuckySignerProvider: () => KentuckySignerProvider,
|
|
24
|
+
RelayerClient: () => RelayerClient,
|
|
25
|
+
createExecutionIntent: () => createExecutionIntent,
|
|
26
|
+
createRelayerClient: () => createRelayerClient,
|
|
27
|
+
signIntent: () => signIntent,
|
|
24
28
|
useAddress: () => useAddress,
|
|
29
|
+
useEstimate: () => useEstimate,
|
|
25
30
|
useIsReady: () => useIsReady,
|
|
26
31
|
useKentuckySigner: () => useKentuckySigner,
|
|
27
32
|
useKentuckySignerAccount: () => useKentuckySignerAccount,
|
|
28
33
|
useKentuckySignerContext: () => useKentuckySignerContext,
|
|
34
|
+
useNonce: () => useNonce,
|
|
29
35
|
usePasskeyAuth: () => usePasskeyAuth,
|
|
36
|
+
useRelayIntent: () => useRelayIntent,
|
|
30
37
|
useSignMessage: () => useSignMessage,
|
|
31
38
|
useSignTypedData: () => useSignTypedData,
|
|
39
|
+
useTransactionStatus: () => useTransactionStatus,
|
|
32
40
|
useWalletClient: () => useWalletClient
|
|
33
41
|
});
|
|
34
42
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -180,9 +188,9 @@ var KentuckySignerClient = class {
|
|
|
180
188
|
/**
|
|
181
189
|
* Sign an EVM transaction hash
|
|
182
190
|
*
|
|
183
|
-
* @param request - Sign request with tx_hash
|
|
191
|
+
* @param request - Sign request with tx_hash
|
|
184
192
|
* @param token - JWT token
|
|
185
|
-
* @returns Signature response with r, s, v components
|
|
193
|
+
* @returns Signature response with r, s, v components (v is always 27 or 28)
|
|
186
194
|
*/
|
|
187
195
|
async signEvmTransaction(request, token) {
|
|
188
196
|
return this.request("/api/sign/evm", {
|
|
@@ -197,13 +205,12 @@ var KentuckySignerClient = class {
|
|
|
197
205
|
* Convenience method that wraps signEvmTransaction.
|
|
198
206
|
*
|
|
199
207
|
* @param hash - 32-byte hash to sign (hex encoded with 0x prefix)
|
|
200
|
-
* @param chainId - Chain ID
|
|
201
208
|
* @param token - JWT token
|
|
202
209
|
* @returns Full signature (hex encoded with 0x prefix)
|
|
203
210
|
*/
|
|
204
|
-
async signHash(hash,
|
|
211
|
+
async signHash(hash, token) {
|
|
205
212
|
const response = await this.signEvmTransaction(
|
|
206
|
-
{ tx_hash: hash
|
|
213
|
+
{ tx_hash: hash },
|
|
207
214
|
token
|
|
208
215
|
);
|
|
209
216
|
return response.signature.full;
|
|
@@ -1037,9 +1044,9 @@ var SecureKentuckySignerClient = class {
|
|
|
1037
1044
|
/**
|
|
1038
1045
|
* Sign a raw hash for EVM (signed request)
|
|
1039
1046
|
*/
|
|
1040
|
-
async signHash(hash,
|
|
1047
|
+
async signHash(hash, token) {
|
|
1041
1048
|
const response = await this.signEvmTransaction(
|
|
1042
|
-
{ tx_hash: hash
|
|
1049
|
+
{ tx_hash: hash },
|
|
1043
1050
|
token
|
|
1044
1051
|
);
|
|
1045
1052
|
return response.signature.full;
|
|
@@ -1259,6 +1266,15 @@ async function authenticateWithPassword(options) {
|
|
|
1259
1266
|
// src/account.ts
|
|
1260
1267
|
var import_viem = require("viem");
|
|
1261
1268
|
var import_accounts = require("viem/accounts");
|
|
1269
|
+
var EIP7702_MAGIC = "0x05";
|
|
1270
|
+
function hashAuthorization(params) {
|
|
1271
|
+
const rlpEncoded = (0, import_viem.toRlp)([
|
|
1272
|
+
params.chainId === 0 ? "0x" : (0, import_viem.numberToHex)(params.chainId),
|
|
1273
|
+
params.contractAddress,
|
|
1274
|
+
params.nonce === 0n ? "0x" : (0, import_viem.numberToHex)(params.nonce)
|
|
1275
|
+
]);
|
|
1276
|
+
return (0, import_viem.keccak256)((0, import_viem.concat)([EIP7702_MAGIC, rlpEncoded]));
|
|
1277
|
+
}
|
|
1262
1278
|
function createKentuckySignerAccount(options) {
|
|
1263
1279
|
const { config, defaultChainId = 1, onSessionExpired, secureClient, on2FARequired } = options;
|
|
1264
1280
|
let session = options.session;
|
|
@@ -1277,14 +1293,17 @@ function createKentuckySignerAccount(options) {
|
|
|
1277
1293
|
}
|
|
1278
1294
|
return session.token;
|
|
1279
1295
|
}
|
|
1280
|
-
|
|
1296
|
+
function ensureHexPrefix(value) {
|
|
1297
|
+
return value.startsWith("0x") ? value : `0x${value}`;
|
|
1298
|
+
}
|
|
1299
|
+
async function signHash(hash) {
|
|
1281
1300
|
const token = await getToken();
|
|
1282
1301
|
try {
|
|
1283
1302
|
const response = await client.signEvmTransaction(
|
|
1284
|
-
{ tx_hash: hash
|
|
1303
|
+
{ tx_hash: hash },
|
|
1285
1304
|
token
|
|
1286
1305
|
);
|
|
1287
|
-
return response.signature.full;
|
|
1306
|
+
return ensureHexPrefix(response.signature.full);
|
|
1288
1307
|
} catch (err) {
|
|
1289
1308
|
if (err instanceof KentuckySignerError && err.code === "2FA_REQUIRED" && on2FARequired) {
|
|
1290
1309
|
const totpRequired = err.message.includes("TOTP") || (err.details?.includes("totp_code") ?? false);
|
|
@@ -1295,24 +1314,24 @@ function createKentuckySignerAccount(options) {
|
|
|
1295
1314
|
throw new KentuckySignerError("2FA verification cancelled", "2FA_CANCELLED", "User cancelled 2FA input");
|
|
1296
1315
|
}
|
|
1297
1316
|
const response = await client.signEvmTransactionWith2FA(
|
|
1298
|
-
{ tx_hash: hash,
|
|
1317
|
+
{ tx_hash: hash, totp_code: codes.totpCode, pin: codes.pin },
|
|
1299
1318
|
token
|
|
1300
1319
|
);
|
|
1301
|
-
return response.signature.full;
|
|
1320
|
+
return ensureHexPrefix(response.signature.full);
|
|
1302
1321
|
}
|
|
1303
1322
|
throw err;
|
|
1304
1323
|
}
|
|
1305
1324
|
}
|
|
1306
|
-
async function signHashWithComponents(hash
|
|
1325
|
+
async function signHashWithComponents(hash) {
|
|
1307
1326
|
const token = await getToken();
|
|
1308
1327
|
try {
|
|
1309
1328
|
const response = await client.signEvmTransaction(
|
|
1310
|
-
{ tx_hash: hash
|
|
1329
|
+
{ tx_hash: hash },
|
|
1311
1330
|
token
|
|
1312
1331
|
);
|
|
1313
1332
|
return {
|
|
1314
|
-
r: response.signature.r,
|
|
1315
|
-
s: response.signature.s,
|
|
1333
|
+
r: ensureHexPrefix(response.signature.r),
|
|
1334
|
+
s: ensureHexPrefix(response.signature.s),
|
|
1316
1335
|
v: response.signature.v
|
|
1317
1336
|
};
|
|
1318
1337
|
} catch (err) {
|
|
@@ -1325,12 +1344,12 @@ function createKentuckySignerAccount(options) {
|
|
|
1325
1344
|
throw new KentuckySignerError("2FA verification cancelled", "2FA_CANCELLED", "User cancelled 2FA input");
|
|
1326
1345
|
}
|
|
1327
1346
|
const response = await client.signEvmTransactionWith2FA(
|
|
1328
|
-
{ tx_hash: hash,
|
|
1347
|
+
{ tx_hash: hash, totp_code: codes.totpCode, pin: codes.pin },
|
|
1329
1348
|
token
|
|
1330
1349
|
);
|
|
1331
1350
|
return {
|
|
1332
|
-
r: response.signature.r,
|
|
1333
|
-
s: response.signature.s,
|
|
1351
|
+
r: ensureHexPrefix(response.signature.r),
|
|
1352
|
+
s: ensureHexPrefix(response.signature.s),
|
|
1334
1353
|
v: response.signature.v
|
|
1335
1354
|
};
|
|
1336
1355
|
}
|
|
@@ -1346,29 +1365,36 @@ function createKentuckySignerAccount(options) {
|
|
|
1346
1365
|
*/
|
|
1347
1366
|
async signMessage({ message }) {
|
|
1348
1367
|
const messageHash = (0, import_viem.hashMessage)(message);
|
|
1349
|
-
return signHash(messageHash
|
|
1368
|
+
return signHash(messageHash);
|
|
1350
1369
|
},
|
|
1351
1370
|
/**
|
|
1352
1371
|
* Sign a transaction
|
|
1353
1372
|
*
|
|
1354
1373
|
* Serializes the transaction, hashes it, signs via Kentucky Signer,
|
|
1355
1374
|
* and returns the signed serialized transaction.
|
|
1375
|
+
*
|
|
1376
|
+
* For legacy transactions, applies EIP-155 encoding (v = chainId * 2 + 35 + recoveryId)
|
|
1377
|
+
* For modern transactions (EIP-1559, EIP-2930, etc.), uses yParity (0 or 1)
|
|
1356
1378
|
*/
|
|
1357
1379
|
async signTransaction(transaction) {
|
|
1358
1380
|
const chainId = transaction.chainId ?? defaultChainId;
|
|
1359
1381
|
const serializedUnsigned = (0, import_viem.serializeTransaction)(transaction);
|
|
1360
1382
|
const txHash = (0, import_viem.keccak256)(serializedUnsigned);
|
|
1361
|
-
const { r, s, v } = await signHashWithComponents(txHash
|
|
1383
|
+
const { r, s, v } = await signHashWithComponents(txHash);
|
|
1384
|
+
const recoveryId = v - 27;
|
|
1385
|
+
let signatureV;
|
|
1362
1386
|
let yParity;
|
|
1363
1387
|
if (transaction.type === "eip1559" || transaction.type === "eip2930" || transaction.type === "eip4844" || transaction.type === "eip7702") {
|
|
1364
|
-
yParity =
|
|
1388
|
+
yParity = recoveryId;
|
|
1389
|
+
signatureV = BigInt(yParity);
|
|
1365
1390
|
} else {
|
|
1366
|
-
|
|
1391
|
+
signatureV = BigInt(chainId * 2 + 35 + recoveryId);
|
|
1392
|
+
yParity = recoveryId;
|
|
1367
1393
|
}
|
|
1368
1394
|
const serializedSigned = (0, import_viem.serializeTransaction)(transaction, {
|
|
1369
1395
|
r,
|
|
1370
1396
|
s,
|
|
1371
|
-
v:
|
|
1397
|
+
v: signatureV,
|
|
1372
1398
|
yParity
|
|
1373
1399
|
});
|
|
1374
1400
|
return serializedSigned;
|
|
@@ -1378,7 +1404,7 @@ function createKentuckySignerAccount(options) {
|
|
|
1378
1404
|
*/
|
|
1379
1405
|
async signTypedData(typedData) {
|
|
1380
1406
|
const hash = (0, import_viem.hashTypedData)(typedData);
|
|
1381
|
-
return signHash(hash
|
|
1407
|
+
return signHash(hash);
|
|
1382
1408
|
}
|
|
1383
1409
|
});
|
|
1384
1410
|
account.source = "kentuckySigner";
|
|
@@ -1391,6 +1417,25 @@ function createKentuckySignerAccount(options) {
|
|
|
1391
1417
|
account.address = newSession.evmAddress;
|
|
1392
1418
|
}
|
|
1393
1419
|
};
|
|
1420
|
+
account.sign7702Authorization = async (params, currentNonce) => {
|
|
1421
|
+
const authNonce = params.executor === "self" ? currentNonce + 1n : params.nonce ?? currentNonce;
|
|
1422
|
+
const chainId = params.chainId ?? defaultChainId;
|
|
1423
|
+
const authHash = hashAuthorization({
|
|
1424
|
+
contractAddress: params.contractAddress,
|
|
1425
|
+
chainId,
|
|
1426
|
+
nonce: authNonce
|
|
1427
|
+
});
|
|
1428
|
+
const { r, s, v } = await signHashWithComponents(authHash);
|
|
1429
|
+
const yParity = v - 27;
|
|
1430
|
+
return {
|
|
1431
|
+
chainId,
|
|
1432
|
+
contractAddress: params.contractAddress,
|
|
1433
|
+
nonce: authNonce,
|
|
1434
|
+
yParity,
|
|
1435
|
+
r,
|
|
1436
|
+
s
|
|
1437
|
+
};
|
|
1438
|
+
};
|
|
1394
1439
|
return account;
|
|
1395
1440
|
}
|
|
1396
1441
|
|
|
@@ -1912,17 +1957,337 @@ function useAddress() {
|
|
|
1912
1957
|
const { account } = useKentuckySignerContext();
|
|
1913
1958
|
return account?.address;
|
|
1914
1959
|
}
|
|
1960
|
+
|
|
1961
|
+
// src/react/relayer-hooks.ts
|
|
1962
|
+
var import_react3 = require("react");
|
|
1963
|
+
function useRelayIntent(client) {
|
|
1964
|
+
const [isRelaying, setIsRelaying] = (0, import_react3.useState)(false);
|
|
1965
|
+
const [response, setResponse] = (0, import_react3.useState)(null);
|
|
1966
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
1967
|
+
const relay = (0, import_react3.useCallback)(
|
|
1968
|
+
async (chainId, accountAddress, signedIntent, paymentMode, authorization) => {
|
|
1969
|
+
setIsRelaying(true);
|
|
1970
|
+
setError(null);
|
|
1971
|
+
try {
|
|
1972
|
+
const result = await client.relay(chainId, accountAddress, signedIntent, paymentMode, authorization);
|
|
1973
|
+
setResponse(result);
|
|
1974
|
+
return result;
|
|
1975
|
+
} catch (err) {
|
|
1976
|
+
const error2 = err instanceof Error ? err : new Error("Relay failed");
|
|
1977
|
+
setError(error2);
|
|
1978
|
+
return { success: false, error: error2.message };
|
|
1979
|
+
} finally {
|
|
1980
|
+
setIsRelaying(false);
|
|
1981
|
+
}
|
|
1982
|
+
},
|
|
1983
|
+
[client]
|
|
1984
|
+
);
|
|
1985
|
+
const reset = (0, import_react3.useCallback)(() => {
|
|
1986
|
+
setResponse(null);
|
|
1987
|
+
setError(null);
|
|
1988
|
+
}, []);
|
|
1989
|
+
return { relay, isRelaying, response, error, reset };
|
|
1990
|
+
}
|
|
1991
|
+
function useTransactionStatus(client, chainId, txHash, pollInterval = 3e3) {
|
|
1992
|
+
const [status, setStatus] = (0, import_react3.useState)(null);
|
|
1993
|
+
const [statusResponse, setStatusResponse] = (0, import_react3.useState)(null);
|
|
1994
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
|
|
1995
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
1996
|
+
const intervalRef = (0, import_react3.useRef)(null);
|
|
1997
|
+
const fetchStatus = (0, import_react3.useCallback)(async () => {
|
|
1998
|
+
if (!txHash) return;
|
|
1999
|
+
setIsLoading(true);
|
|
2000
|
+
try {
|
|
2001
|
+
const response = await client.getStatus(chainId, txHash);
|
|
2002
|
+
setStatusResponse(response);
|
|
2003
|
+
setStatus(response.status);
|
|
2004
|
+
setError(null);
|
|
2005
|
+
if (response.status === "confirmed" || response.status === "failed") {
|
|
2006
|
+
if (intervalRef.current) {
|
|
2007
|
+
clearInterval(intervalRef.current);
|
|
2008
|
+
intervalRef.current = null;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
} catch (err) {
|
|
2012
|
+
setError(err instanceof Error ? err : new Error("Failed to fetch status"));
|
|
2013
|
+
} finally {
|
|
2014
|
+
setIsLoading(false);
|
|
2015
|
+
}
|
|
2016
|
+
}, [client, chainId, txHash]);
|
|
2017
|
+
(0, import_react3.useEffect)(() => {
|
|
2018
|
+
if (!txHash) {
|
|
2019
|
+
setStatus(null);
|
|
2020
|
+
setStatusResponse(null);
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
fetchStatus();
|
|
2024
|
+
intervalRef.current = setInterval(fetchStatus, pollInterval);
|
|
2025
|
+
return () => {
|
|
2026
|
+
if (intervalRef.current) {
|
|
2027
|
+
clearInterval(intervalRef.current);
|
|
2028
|
+
intervalRef.current = null;
|
|
2029
|
+
}
|
|
2030
|
+
};
|
|
2031
|
+
}, [txHash, pollInterval, fetchStatus]);
|
|
2032
|
+
return { status, statusResponse, isLoading, error, refresh: fetchStatus };
|
|
2033
|
+
}
|
|
2034
|
+
function useEstimate(client) {
|
|
2035
|
+
const [estimateResponse, setEstimateResponse] = (0, import_react3.useState)(null);
|
|
2036
|
+
const [isEstimating, setIsEstimating] = (0, import_react3.useState)(false);
|
|
2037
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
2038
|
+
const estimate = (0, import_react3.useCallback)(
|
|
2039
|
+
async (chainId, accountAddress, intent) => {
|
|
2040
|
+
setIsEstimating(true);
|
|
2041
|
+
setError(null);
|
|
2042
|
+
try {
|
|
2043
|
+
const response = await client.estimate(chainId, accountAddress, intent);
|
|
2044
|
+
setEstimateResponse(response);
|
|
2045
|
+
return response;
|
|
2046
|
+
} catch (err) {
|
|
2047
|
+
const error2 = err instanceof Error ? err : new Error("Estimate failed");
|
|
2048
|
+
setError(error2);
|
|
2049
|
+
return null;
|
|
2050
|
+
} finally {
|
|
2051
|
+
setIsEstimating(false);
|
|
2052
|
+
}
|
|
2053
|
+
},
|
|
2054
|
+
[client]
|
|
2055
|
+
);
|
|
2056
|
+
return { estimate, estimateResponse, isEstimating, error };
|
|
2057
|
+
}
|
|
2058
|
+
function useNonce(client, chainId, address) {
|
|
2059
|
+
const [nonce, setNonce] = (0, import_react3.useState)(null);
|
|
2060
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
|
|
2061
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
2062
|
+
const fetchNonce = (0, import_react3.useCallback)(async () => {
|
|
2063
|
+
if (!address) return;
|
|
2064
|
+
setIsLoading(true);
|
|
2065
|
+
try {
|
|
2066
|
+
const result = await client.getNonce(chainId, address);
|
|
2067
|
+
setNonce(result);
|
|
2068
|
+
setError(null);
|
|
2069
|
+
} catch (err) {
|
|
2070
|
+
setError(err instanceof Error ? err : new Error("Failed to fetch nonce"));
|
|
2071
|
+
} finally {
|
|
2072
|
+
setIsLoading(false);
|
|
2073
|
+
}
|
|
2074
|
+
}, [client, chainId, address]);
|
|
2075
|
+
(0, import_react3.useEffect)(() => {
|
|
2076
|
+
if (address) {
|
|
2077
|
+
fetchNonce();
|
|
2078
|
+
} else {
|
|
2079
|
+
setNonce(null);
|
|
2080
|
+
}
|
|
2081
|
+
}, [address, fetchNonce]);
|
|
2082
|
+
return { nonce, isLoading, error, refresh: fetchNonce };
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
// src/relayer-client.ts
|
|
2086
|
+
var RelayerClient = class {
|
|
2087
|
+
constructor(options) {
|
|
2088
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
2089
|
+
this.timeout = options.timeout ?? 3e4;
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Check if the relayer is healthy
|
|
2093
|
+
*/
|
|
2094
|
+
async health() {
|
|
2095
|
+
const response = await this.fetch("/health");
|
|
2096
|
+
return response;
|
|
2097
|
+
}
|
|
2098
|
+
/**
|
|
2099
|
+
* Get the current nonce for an account
|
|
2100
|
+
*
|
|
2101
|
+
* @param chainId - Chain ID
|
|
2102
|
+
* @param address - Account address
|
|
2103
|
+
* @returns Current nonce as bigint
|
|
2104
|
+
*/
|
|
2105
|
+
async getNonce(chainId, address) {
|
|
2106
|
+
const response = await this.fetch(`/nonce/${chainId}/${address}`);
|
|
2107
|
+
return BigInt(response.nonce);
|
|
2108
|
+
}
|
|
2109
|
+
/**
|
|
2110
|
+
* Estimate gas and fees for an intent
|
|
2111
|
+
*
|
|
2112
|
+
* @param chainId - Chain ID
|
|
2113
|
+
* @param accountAddress - Account address (the delegated EOA)
|
|
2114
|
+
* @param intent - Execution intent
|
|
2115
|
+
* @returns Estimate response
|
|
2116
|
+
*/
|
|
2117
|
+
async estimate(chainId, accountAddress, intent) {
|
|
2118
|
+
const response = await this.fetch("/estimate", {
|
|
2119
|
+
method: "POST",
|
|
2120
|
+
body: JSON.stringify({
|
|
2121
|
+
chainId,
|
|
2122
|
+
accountAddress,
|
|
2123
|
+
intent: {
|
|
2124
|
+
nonce: intent.nonce.toString(),
|
|
2125
|
+
deadline: intent.deadline.toString(),
|
|
2126
|
+
target: intent.target,
|
|
2127
|
+
value: intent.value.toString(),
|
|
2128
|
+
data: intent.data
|
|
2129
|
+
}
|
|
2130
|
+
})
|
|
2131
|
+
});
|
|
2132
|
+
return response;
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Relay a signed intent
|
|
2136
|
+
*
|
|
2137
|
+
* @param chainId - Chain ID
|
|
2138
|
+
* @param accountAddress - Account address (the delegated EOA)
|
|
2139
|
+
* @param signedIntent - Signed execution intent
|
|
2140
|
+
* @param paymentMode - Payment mode ('sponsored' or { token: Address })
|
|
2141
|
+
* @param authorization - Optional EIP-7702 authorization for gasless onboarding
|
|
2142
|
+
* @returns Relay response with transaction hash
|
|
2143
|
+
*
|
|
2144
|
+
* @example Gasless onboarding (delegate + execute in one tx)
|
|
2145
|
+
* ```typescript
|
|
2146
|
+
* // Get current nonce for authorization
|
|
2147
|
+
* const txNonce = await publicClient.getTransactionCount({ address: accountAddress })
|
|
2148
|
+
*
|
|
2149
|
+
* // Sign EIP-7702 authorization
|
|
2150
|
+
* const authorization = await account.sign7702Authorization({
|
|
2151
|
+
* contractAddress: delegateAddress,
|
|
2152
|
+
* chainId: 42161,
|
|
2153
|
+
* }, txNonce)
|
|
2154
|
+
*
|
|
2155
|
+
* // Relay with authorization
|
|
2156
|
+
* const result = await relayer.relay(
|
|
2157
|
+
* 42161,
|
|
2158
|
+
* accountAddress,
|
|
2159
|
+
* signedIntent,
|
|
2160
|
+
* 'sponsored',
|
|
2161
|
+
* authorization
|
|
2162
|
+
* )
|
|
2163
|
+
* ```
|
|
2164
|
+
*/
|
|
2165
|
+
async relay(chainId, accountAddress, signedIntent, paymentMode, authorization) {
|
|
2166
|
+
const body = {
|
|
2167
|
+
chainId,
|
|
2168
|
+
accountAddress,
|
|
2169
|
+
intent: {
|
|
2170
|
+
nonce: signedIntent.intent.nonce.toString(),
|
|
2171
|
+
deadline: signedIntent.intent.deadline.toString(),
|
|
2172
|
+
target: signedIntent.intent.target,
|
|
2173
|
+
value: signedIntent.intent.value.toString(),
|
|
2174
|
+
data: signedIntent.intent.data
|
|
2175
|
+
},
|
|
2176
|
+
ownerSignature: signedIntent.signature,
|
|
2177
|
+
paymentMode
|
|
2178
|
+
};
|
|
2179
|
+
if (authorization) {
|
|
2180
|
+
body.authorization = {
|
|
2181
|
+
chainId: authorization.chainId,
|
|
2182
|
+
contractAddress: authorization.contractAddress,
|
|
2183
|
+
nonce: authorization.nonce.toString(),
|
|
2184
|
+
yParity: authorization.yParity,
|
|
2185
|
+
r: authorization.r,
|
|
2186
|
+
s: authorization.s
|
|
2187
|
+
};
|
|
2188
|
+
}
|
|
2189
|
+
const response = await this.fetch("/relay", {
|
|
2190
|
+
method: "POST",
|
|
2191
|
+
body: JSON.stringify(body)
|
|
2192
|
+
});
|
|
2193
|
+
return response;
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Get transaction status
|
|
2197
|
+
*
|
|
2198
|
+
* @param chainId - Chain ID
|
|
2199
|
+
* @param txHash - Transaction hash
|
|
2200
|
+
* @returns Status response
|
|
2201
|
+
*/
|
|
2202
|
+
async getStatus(chainId, txHash) {
|
|
2203
|
+
const response = await this.fetch(`/status/${chainId}/${txHash}`);
|
|
2204
|
+
return response;
|
|
2205
|
+
}
|
|
2206
|
+
/**
|
|
2207
|
+
* Make a fetch request to the relayer API
|
|
2208
|
+
*/
|
|
2209
|
+
async fetch(path, options) {
|
|
2210
|
+
const controller = new AbortController();
|
|
2211
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
2212
|
+
try {
|
|
2213
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
2214
|
+
...options,
|
|
2215
|
+
headers: {
|
|
2216
|
+
"Content-Type": "application/json",
|
|
2217
|
+
...options?.headers
|
|
2218
|
+
},
|
|
2219
|
+
signal: controller.signal
|
|
2220
|
+
});
|
|
2221
|
+
const data = await response.json();
|
|
2222
|
+
if (!response.ok) {
|
|
2223
|
+
throw new Error(data.error || `Request failed: ${response.status}`);
|
|
2224
|
+
}
|
|
2225
|
+
return data;
|
|
2226
|
+
} finally {
|
|
2227
|
+
clearTimeout(timeoutId);
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
};
|
|
2231
|
+
function createRelayerClient(baseUrl) {
|
|
2232
|
+
return new RelayerClient({ baseUrl });
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
// src/intent.ts
|
|
2236
|
+
var import_viem3 = require("viem");
|
|
2237
|
+
var INTENT_TYPEHASH = (0, import_viem3.keccak256)(
|
|
2238
|
+
(0, import_viem3.encodePacked)(
|
|
2239
|
+
["string"],
|
|
2240
|
+
["ExecutionIntent(uint256 nonce,uint256 deadline,address target,uint256 value,bytes data)"]
|
|
2241
|
+
)
|
|
2242
|
+
);
|
|
2243
|
+
function createExecutionIntent(params) {
|
|
2244
|
+
return {
|
|
2245
|
+
nonce: params.nonce,
|
|
2246
|
+
deadline: params.deadline ?? BigInt(Math.floor(Date.now() / 1e3) + 3600),
|
|
2247
|
+
// 1 hour default
|
|
2248
|
+
target: params.target,
|
|
2249
|
+
value: params.value ?? 0n,
|
|
2250
|
+
data: params.data ?? "0x"
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
function hashIntent(intent) {
|
|
2254
|
+
const dataHash = (0, import_viem3.keccak256)(intent.data);
|
|
2255
|
+
return (0, import_viem3.keccak256)(
|
|
2256
|
+
(0, import_viem3.encodeAbiParameters)(
|
|
2257
|
+
(0, import_viem3.parseAbiParameters)("bytes32, uint256, uint256, address, uint256, bytes32"),
|
|
2258
|
+
[INTENT_TYPEHASH, intent.nonce, intent.deadline, intent.target, intent.value, dataHash]
|
|
2259
|
+
)
|
|
2260
|
+
);
|
|
2261
|
+
}
|
|
2262
|
+
async function signIntent(account, intent) {
|
|
2263
|
+
const intentHash = hashIntent(intent);
|
|
2264
|
+
const signature = await account.signMessage({
|
|
2265
|
+
message: { raw: intentHash }
|
|
2266
|
+
});
|
|
2267
|
+
return {
|
|
2268
|
+
intent,
|
|
2269
|
+
signature
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
1915
2272
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1916
2273
|
0 && (module.exports = {
|
|
1917
2274
|
KentuckySignerProvider,
|
|
2275
|
+
RelayerClient,
|
|
2276
|
+
createExecutionIntent,
|
|
2277
|
+
createRelayerClient,
|
|
2278
|
+
signIntent,
|
|
1918
2279
|
useAddress,
|
|
2280
|
+
useEstimate,
|
|
1919
2281
|
useIsReady,
|
|
1920
2282
|
useKentuckySigner,
|
|
1921
2283
|
useKentuckySignerAccount,
|
|
1922
2284
|
useKentuckySignerContext,
|
|
2285
|
+
useNonce,
|
|
1923
2286
|
usePasskeyAuth,
|
|
2287
|
+
useRelayIntent,
|
|
1924
2288
|
useSignMessage,
|
|
1925
2289
|
useSignTypedData,
|
|
2290
|
+
useTransactionStatus,
|
|
1926
2291
|
useWalletClient
|
|
1927
2292
|
});
|
|
1928
2293
|
//# sourceMappingURL=index.js.map
|