UNPKG

@hazbase/relayer

Version:

The relayer SDK that provides gasless execution (meta-transactions) for the hazBase stack.

268 lines (260 loc) 9.48 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { CHAIN_ID_TO_NETWORK: () => CHAIN_ID_TO_NETWORK, FORWARDER_ABI: () => FORWARDER_ABI, RELAYERS: () => RELAYERS, TOKEN_ABI: () => TOKEN_ABI, bigintReplacer: () => bigintReplacer, buildForwardRequest: () => buildForwardRequest, forwardCall: () => forwardCall, generateRelayerAuthCode: () => generateRelayerAuthCode, getForwarderAddress: () => getForwarderAddress, getRelayerUrl: () => getRelayerUrl, makeDomain: () => makeDomain, sendRelayerTransaction: () => sendRelayerTransaction, signForwardRequest: () => signForwardRequest }); module.exports = __toCommonJS(index_exports); // src/constants.ts var RELAYERS = { hazama: { forwarderAddress: "" }, /* ---------- Mainnet ---------- */ ethereum: { forwarderAddress: "0xc82BbE41f2cF04e3a8efA18F7032BDD7f6d98a81" }, polygon: { forwarderAddress: "0xc82BbE41f2cF04e3a8efA18F7032BDD7f6d98a81" }, astar: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, "astar-zkevm": { forwarderAddress: "0x1576910A5Ba1781b1d88278DaC3729B11f415388" }, celo: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, binance: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, avalanche: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, "polygon-zkevm": { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, worldchain: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, soneium: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, /* ---------- Testnet ---------- */ mumbai: { forwarderAddress: "0xc82BbE41f2cF04e3a8efA18F7032BDD7f6d98a81" }, goerli: { forwarderAddress: "0x5001A14CA6163143316a7C614e30e6041033Ac20" }, sepolia: { forwarderAddress: "0x5Eec1A55ADf49Ef53E7AeB6749655E91cE8b9660" }, "celo-alfajores-testnet": { forwarderAddress: "0x39B6A5eCa1737c71aF9f909F25475976851F26D6" }, "binance-testnet": { forwarderAddress: "0x39B6A5eCa1737c71aF9f909F25475976851F26D6" }, "avalanche-fuji": { forwarderAddress: "0x39B6A5eCa1737c71aF9f909F25475976851F26D6" }, "polygon-zkevm-testnet": { forwarderAddress: "0x39B6A5eCa1737c71aF9f909F25475976851F26D6" }, zkatana: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, "polygon-amoy-testnet": { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, "polygon-zkevm-cardona-testnet": { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, zkyoto: { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, "soneium-minato": { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, "worldchain-sepolia": { forwarderAddress: "0x2fA9F95Fe9dD8469D6Da3B65Aa2bFdD96eAC86F0" }, /* ---------- Not set ---------- */ rinkeby: { forwarderAddress: "" }, shiden: { forwarderAddress: "" } }; var CHAIN_ID_TO_NETWORK = { 1: "ethereum", 4: "rinkeby", 5: "goerli", 137: "polygon", 592: "astar", 80001: "mumbai", 336: "shiden", 42220: "celo", 44787: "celo-alfajores-testnet", 56: "binance", 97: "binance-testnet", 43114: "avalanche", 43113: "avalanche-fuji", 1101: "polygon-zkevm", 1442: "polygon-zkevm-testnet", 1261120: "zkatana", 3776: "astar-zkevm", 11155111: "sepolia", 80002: "polygon-amoy-testnet", 2442: "polygon-zkevm-cardona-testnet", 6038361: "zkyoto", 1946: "soneium-minato", 1868: "soneium", 480: "worldchain", 4801: "worldchain-sepolia" }; var TOKEN_ABI = [ "function decimals() view returns(uint8)", "function transfer(address,uint256) external returns(bool)", "function nonces(address) view returns(uint256)" ]; var FORWARDER_ABI = [ "function getNonce(address) view returns (uint256)", "function execute((address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data),bytes) payable returns (bytes)" ]; // src/utils.ts var import_auth = require("@hazbase/auth"); function getRelayerUrl(chainId) { const net = CHAIN_ID_TO_NETWORK[chainId]; if (!net) throw new Error(`Unsupported chainId: ${chainId}`); return `${(0, import_auth.getApiEndpoint)()}/api/app/relayer/send-function?network=${net}`; } function getForwarderAddress(chainId) { const net = CHAIN_ID_TO_NETWORK[chainId]; if (!net) throw new Error(`Unsupported chainId: ${chainId}`); const entry = RELAYERS[net]; if (!entry?.forwarderAddress) throw new Error(`No Forwarder configured for network: ${net}`); return entry.forwarderAddress; } function bigintReplacer(_k, v) { return typeof v === "bigint" ? v.toString() : v; } // src/codeGen.ts var import_auth2 = require("@hazbase/auth"); async function generateRelayerAuthCode({ accessToken, chainId, contractAddress, type = "relayer_auth" }) { const clientKey = await (0, import_auth2.ensureClientKeyActive)(70); const res = await fetch(`${(0, import_auth2.getApiEndpoint)()}/api/app/code/generate-code`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${accessToken}` }, body: JSON.stringify({ type, chainId, contractAddress, forSelf: false, clientKey }) }); if (!res.ok) throw new Error("GenCode error"); const { data } = await res.json(); (0, import_auth2.createRequestTransaction)({ functionId: 70, status: "succeeded", isCount: true }); return data.code; } // src/forward.ts var import_ethers = require("ethers"); var import_auth3 = require("@hazbase/auth"); async function buildForwardRequest({ signer, tokenAddress, chainId }) { await (0, import_auth3.ensureClientKeyActive)(71); const from = await signer.getAddress(); const forwarder = new import_ethers.ethers.Contract(getForwarderAddress(chainId), FORWARDER_ABI, signer); const nonce = await forwarder.getNonce(from); (0, import_auth3.createRequestTransaction)({ functionId: 71, status: "succeeded", isCount: true }); return { from, to: tokenAddress, value: "0", gas: 5e5, nonce: Number(nonce), data: "" }; } function makeDomain(chainId) { return { name: "GSNv2 Forwarder", version: "0.0.1", chainId, verifyingContract: getForwarderAddress(chainId) }; } async function signForwardRequest({ signer, domain, request }) { const types = { ForwardRequest: [ { name: "from", type: "address" }, { name: "to", type: "address" }, { name: "value", type: "uint256" }, { name: "gas", type: "uint256" }, { name: "nonce", type: "uint256" }, { name: "data", type: "bytes" } ] }; return signer.signTypedData(domain, types, request); } // src/relayer.ts var import_auth4 = require("@hazbase/auth"); async function sendRelayerTransaction({ chainId, code, request, signature }) { await (0, import_auth4.ensureClientKeyActive)(73); const base = getRelayerUrl(chainId); const url = `${base}&code=${code}&forSelf=false`; const res = await fetch(url, { method: "POST", headers: { "Content-Type": "text/plain" }, body: JSON.stringify({ request, signature, type: "forward" }, bigintReplacer) }); if (!res.ok) throw new Error("Relayer error"); const { result } = await res.json(); (0, import_auth4.createRequestTransaction)({ functionId: 73, status: "succeeded", isCount: true }); return JSON.parse(result); } // src/forwardCall.ts var import_ethers2 = require("ethers"); var import_auth5 = require("@hazbase/auth"); async function forwardCall(p) { await (0, import_auth5.ensureClientKeyActive)(72); const contract = new import_ethers2.ethers.Contract(p.contractAddress, p.abi, p.signer); const data = contract.interface.encodeFunctionData(p.method, p.args); const request = await buildForwardRequest({ signer: p.signer, tokenAddress: p.contractAddress, chainId: p.chainId }); request.data = data; const domain = makeDomain(p.chainId); const signature = await signForwardRequest({ signer: p.signer, domain, request }); const code = await generateRelayerAuthCode({ accessToken: p.accessToken, chainId: p.chainId, contractAddress: p.contractAddress }); (0, import_auth5.createRequestTransaction)({ functionId: 72, status: "succeeded", isCount: true }); return sendRelayerTransaction({ chainId: p.chainId, code, request, signature }); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { CHAIN_ID_TO_NETWORK, FORWARDER_ABI, RELAYERS, TOKEN_ABI, bigintReplacer, buildForwardRequest, forwardCall, generateRelayerAuthCode, getForwarderAddress, getRelayerUrl, makeDomain, sendRelayerTransaction, signForwardRequest });