@hazbase/relayer
Version:
The relayer SDK that provides gasless execution (meta-transactions) for the hazBase stack.
268 lines (260 loc) • 9.48 kB
JavaScript
;
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
});