0.0.22 • Published 10 months ago
@resolverworks/ezccip v0.0.22
ezccip.js
Turnkey EIP-3668: CCIP-Read Handler for ENS and arbitrary functions.
npm i @resolverworks/ezccip
✓
- see types / uses ethers
- works with any server infrastructure * uses minimal imports for serverless
- implements multiple protocols:
"tor"
— resolverworks/TheOffchainResolver.sol"ens"
— ensdomains/offchain-resolver and ccip.tools *"raw"
— raw response (EVM Gateway, testing, etc.) - used by resolverworks/TheOffchainGateway.js
enableENSIP10()
drop-in support for resolverworks/enson.js Record-type- supports Multicall-over-CCIP-Read
resolve(name, multicall([...]))
multicall([resolve(name, ...), ...])
*multicall([resolve(name, multicall([...])), ...])
- use
serve()
to quickly launch a server - CCIP Postman ⭐️ * directly debug any CCIP-Read server (no RPC)
Demo
npm run start
— starts a CCIP-Read server for TOR protocol usingserve()
- check Postman ← change to
http://localhost:8016
- choose a TOR:
- setup Context:
0xd00d726b2aD6C81E894DC6B87BE6Ce9c5572D2cd http://localhost:8016
Examples
- DNS (using
"tor"
protocol on Mainnet):ezccip.raffy.xyz
Resolver:0x7CE6Cf740075B5AF6b1681d67136B84431B43AbD
Context:0xd00d726b2aD6C81E894DC6B87BE6Ce9c5572D2cd https://raffy.xyz/ezccip/0x7CE6Cf740075B5AF6b1681d67136B84431B43AbD
- ENS (using
"tor"
protocol on Sepolia):ezccip.eth
Resolver:0x3c187BAb6dC2C94790d4dA5308672e6F799DcEC3
Context:0xd00d726b2aD6C81E894DC6B87BE6Ce9c5572D2cd https://raffy.xyz/ezccip/0x3c187BAb6dC2C94790d4dA5308672e6F799DcEC3
- DNS (using
"ens"
protocol on Mainnet)ens.ezccip.raffy.xyz
Resolver: 0x3CA097Edd180Ea2C2436BD30c021Ca20869087a0 Contect:0xd00d726b2aD6C81E894DC6B87BE6Ce9c5572D2cd https://raffy.xyz/ezccip/0x3CA097Edd180Ea2C2436BD30c021Ca20869087a0
Usage
Create an instance and register some handlers.
import {EZCCIP} from '@resolverworks/ezccip';
let ezccip = new EZCCIP();
// implement an arbitrary function
ezccip.register('add(uint256, uint256) returns (uint256)', ([a, b]) => [a + b]);
// implement a wildcard ENSIP-10 resolver
// which handles resolve() automatically
ezccip.enableENSIP10(async (name, context) => {
return {
async text(key) {
switch (key) {
case 'name': return 'Raffy';
case 'avatar': return 'https://raffy.antistupid.com/ens.jpg';
}
},
};
});
// more complicated example
let abi = new ethers.Interface([
'function f(bytes32 x) returns (string)',
'function g(uint256 a, uint256 b) returns (uint256)',
]);
ezccip.register(abi, { // register multiple functions at once using existing ABI
async ['f(bytes32)']([x], context, history) { // match function by signature
history.show = [context.sender]; // replace arguments of f(...) in logger
history.name = 'Chonk'; // rename f() to Chonk() in logger
return [context.calldata]; // echo incoming calldata
},
async ['0xe2179b8e']([a, b], context) { // match by selector
context.protocol = "tor"; // override signing protocol
return ethers.toBeHex(1337n, 32); // return raw encoded result
}
});
When your server has a request for CCIP-Read, use EZCCIP to produce a response.
let {sender, data: calldata} = JSON.parse(req.body); // ABI-encoded request in JSON from EIP-3668
let {data, history} = await ezccip.handleRead(sender, calldata, {
protocol: 'tor', // default, tor requires signingKey + resolver
signingKey, // your private key
});
reply.json({data}); // ABI-encoded response in JSON for EIP-3668
console.log(history.toString()); // description of response
- implement via
GET
,POST
, or query directly context
carries useful information about the incoming requesthistory
collects information as the response is generated
serve()
Start a simple server for an EZCCIP instance or a function representing the enableENSIP10()
handler.
import {serve} from '@resolverworks/ezccip/serve';
let ccip = await serve(ezccip); // see types for more configuration
// ...
await ccip.shutdown();
// minimal example:
// return fixed text() for any name
await serve(() => { text: () => 'Raffy' });
Sender vs Origin
- ⚠️
sender
may not be the originating contract * see: recursive CCIP-Read - Best Solution: embed
origin
into the endpoint as a path component: 1.http://my.server/.../0xABCD/...
1.origin = 0xABCD
- or, use
parseOrigin(path: string) => string
to extractorigin
from an arbitrary path - or, supply a fallback
origin
- if
origin
is not detected,origin = sender
processENSIP10()
Apply ENSIP-10 calldata
to a Record
-object and generate the corresponding ABI-encoded response. This is a free-function.
let record = {
text(key) { if (key == 'name') return 'raffy'; }
addr(type) { if (type == 60) return '0x1234'; }
};
let calldata = '0x...'; // encodeFunctionData('text', ['name']);
let res = await processENSIP10(record, calldata); // encodeFunctionResult('text', ['raffy']);
0.0.22
10 months ago
0.0.21
10 months ago
0.0.20
10 months ago
0.0.16
10 months ago
0.0.17
10 months ago
0.0.18
10 months ago
0.0.19
10 months ago
0.0.15
11 months ago
0.0.12
1 year ago
0.0.13
1 year ago
0.0.14
12 months ago
0.0.11
1 year ago
0.0.10
1 year ago
0.0.9
1 year ago
0.0.8
1 year ago
0.0.7
1 year ago
0.0.5
1 year ago
0.0.6
1 year ago
0.0.3
1 year ago
0.0.4
1 year ago
0.0.2
1 year ago
0.0.1
1 year ago