🤝 Type-safe P2P RPC that just works. A 🍐 project.
- Simple API: Build P2P services with minimal boilerplate
- Developer Experience: Interactive testing UI included
- Trust: Define clear contracts between peers
- Type Safety: Full TypeScript/JSDoc support with runtime validation
npm i @agree-able/contract @agreeable/rpc
import { z, addRoute } from '@agree-able/contract'
// Define your functions with Zod
export const AddTwo = z.function()
.args(z.object({
a: z.number(),
b: z.number()
}))
.returns(z.promise(z.number()))
// Create the API contract
export default {
role: 'calculator',
version: '1.0.0',
routes: {
addTwo: addRoute(AddTwo)
}
}
// @ts-check
import { loadAgreement, host } from '@agree-able/rpc'
import { AddTwo } from './agreement.mjs'
/** @type { z.infer<AddTwo> } addTwo */
const addTwo = async ({a, b}) => a + b
host(await loadAgreement('./agreement.mjs', import.meta.url), { addTwo })
// @ts-check
import { Caller } from '@agree-able/rpc'
import agreement, { AddTwo } from './agreement.mjs'
const peerKey = process.argv[2]
const caller = new Caller(peerKey)
/** @type{{
* addTwo: z.infer<AddTwo>
* }} */
// @ts-expect-error
const { addTwo } = caller.proxy(agreement)
// Call remote functions
const result = await addTwo({ a: 1, b: 2 })
console.log(result) // 3
caller.destroy()
- Start the server:
node server.mjs
# Will print a public key like: 3e32bb2d191316d952ae77439f7ec00a5c4fea8a01953b84d1b4eee36173e1ca
- Run the client with the server's public key:
node client.mjs 3e32bb2d191316d952ae77439f7ec00a5c4fea8a01953b84d1b4eee36173e1ca
Use our UI tool to explore and test your APIs: https://github.com/agree-able/ui
We welcome contributions! See our contributing guide for details.