@witnessco/paygo-ts-client
v0.2.1
Published
## Introduction
Readme
@witnessco/paygo-ts-client
Introduction
Paygo is a verifiable payments protocol that enables secure, efficient, and provable transactions on the blockchain. Built using the verifiable application pattern, Paygo processes transactions in real-time while maintaining provable state changes and periodic snapshots, all at an extremely low cost of ~$0.00005 per transaction.
This TypeScript client provides a simple interface for integrating Paygo into your applications. You can create and manage accounts, send and receive payments, create conditional escrows with zk-proof support, delegate payment authority between accounts, and track transaction history.
Installation
# Using bun
bun add @witnessco/paygo-ts-clientQuick Start
import { PaygoClient } from "@witnessco/paygo-ts-client";
// Create a client with local signing
const client = new PaygoClient();
await client.setPk('0x...');
// Or create a client with viem wallet
const client = new PaygoClient({
viemWalletClient: createWalletClient({
account: privateKeyToAccount('0x...'),
transport: http('https://eth-mainnet.g.alchemy.com/v2/demo'),
chain: mainnet,
}),
});
// Request tokens from faucet
const faucetRequest = new FaucetRequest(1000000000000000000n); // amount in cents
const faucetResponse = await client.signAndPostTransactionFromParams(faucetRequest);
console.log(`Faucet request sent: ${faucetResponse.hash}`);
// Create and send a transfer
const transfer = new Transfer(
'0x1234...', // recipient address
1000000000000000000n // amount in cents
);
const transferResponse = await client.signAndPostTransactionFromParams(transfer);
console.log(`Transfer: ${transferResponse.hash}`);Features
Accounts
Accounts in Paygo are similar to EVM-style addresses but with a simpler structure. Each account has an address, a nonce for transaction ordering, and a balance in cents. These accounts form the foundation of the Paygo system, allowing users to interact with it.
import { PaygoClient } from "@witnessco/paygo-ts-client";
const client = new PaygoClient();
await client.setPk('0x...');
// Get current address
const address = await client.address();
console.log(`Current address: ${address}`);
// Get account information
const account = await client.getAccount(address);
console.log(`Account balance: ${account.balance}`);
console.log(`Account nonce: ${account.nonce}`);Delegations
Delegations provide a powerful way to manage shared funds and create payment authorization systems. They allow one account (the delegator) to grant spending authority to another account (the delegate), with controls for maximum spending amounts and expiration dates. This enables use cases like managing shared funds, creating payment authorization systems, and implementing multi-signature-like functionality.
import { PaygoClient, UpsertDelegation, DelegateTransfer } from "@witnessco/paygo-ts-client";
import { hashMessage } from "viem";
const client = new PaygoClient();
await client.setPk('0x...');
// Create a delegation
const delegationId = hashMessage(crypto.randomUUID()); // 32 byte random hash
const delegation = new UpsertDelegation(
delegationId,
'0x1234...', // delegate address
1000000000000000000n, // allowance
new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) // expiration (30 days)
);
const response = await client.signAndPostTransactionFromParams(delegation);
console.log(`Delegation created: ${response.hash}`);
// Make a delegated transfer
const delegatedTransfer = new DelegateTransfer(
delegationId,
100000000000000000n, // amount
'0x5678...' // recipient
);
const transfer = await client.signAndPostTransactionFromParams(delegatedTransfer);
console.log(`Delegated transfer sent: ${transfer.hash}`);Escrows
Escrows in Paygo provide a flexible way to handle conditional payments and time-locked funds. They allow you to lock funds with specific conditions that can be satisfied with an SP1 zk proof, making them ideal for multi-party agreements and conditional payments. Each escrow has a unique ID, locked amount, expiration date, and optional fulfiller address and proof requirements. Funds can be released when conditions are met or when the escrow expires.
import { PaygoClient, CreateEscrow, FulfillEscrow, ReleaseEscrow } from "@witnessco/paygo-ts-client";
import { hashMessage } from "viem";
const client = new PaygoClient();
await client.setPk('0x...');
// Create an escrow
const escrowId = hashMessage(crypto.randomUUID()); // 32 byte random hash
const createEscrow = new CreateEscrow(
escrowId,
1000000000000000000n, // amount
new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // expiration (30 days)
'0x1234...', // optional fulfiller address
'0x0000000000000000000000000000000000000000000000000000000000000000' // optional vkey of an sp1 circuit
);
const response = await client.signAndPostTransactionFromParams(createEscrow);
console.log(`Escrow created: ${response.hash}`);
// Fulfill an escrow
const fulfillEscrow = new FulfillEscrow(
escrowId,
'0x0000000000000000000000000000000000000000000000000000000000000000' // proof
);
const fulfillment = await client.signAndPostTransactionFromParams(fulfillEscrow);
console.log(`Escrow fulfilled: ${fulfillment.hash}`);
// Release an expired escrow
const releaseEscrow = new ReleaseEscrow(escrowId);
const release = await client.signAndPostTransactionFromParams(releaseEscrow);
console.log(`Escrow released: ${release.hash}`);Transaction History
Paygo maintains a complete and verifiable history of all transactions. You can query transactions by their hash, the signer's address, or the block number they were included in. This comprehensive history allows for easy tracking and verification of all operations on the network, ensuring transparency and auditability.
import { PaygoClient } from "@witnessco/paygo-ts-client";
const client = new PaygoClient();
await client.setPk('0x...');
// Get transaction by hash
const tx = await client.getTransactionByHash('0x1234...');
console.log(`Transaction status: ${tx?.status}`);
// Get transactions by signer
const txs = await client.getTransactionsBySigner(await client.address());
txs.forEach(tx => {
console.log(`Transaction ${tx}: ${tx.status}`);
});
// Get transactions in a block
const blockTxs = await client.getTransactionsByBlock(123456n);
console.log(`Found ${blockTxs.length} transactions in block 123456`);Viem Integration
The Paygo client supports integration with viem, a TypeScript interface for Ethereum that provides a consistent API for interacting with Ethereum nodes. This allows you to use Paygo with any viem-compatible wallet or provider.
Setting Up Viem
import { PaygoClient } from "@witnessco/paygo-ts-client";
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';
// Create a viem wallet client
const viemWalletClient = createWalletClient({
account: privateKeyToAccount('0x...'), // or use any other viem account
transport: http('https://eth-mainnet.g.alchemy.com/v2/demo'),
chain: mainnet,
});
// Create a Paygo client with viem
const client = new PaygoClient({
viemWalletClient,
});
// Use the client as normal
const address = await client.address();
console.log(`Connected address: ${address}`);Switching Between Signing Methods
You can switch between local signing and viem signing at any time:
import { PaygoClient, SignerConfig } from "@witnessco/paygo-ts-client";
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';
// Start with local signing
const client = new PaygoClient();
await client.setPk('0x...');
// Create a viem wallet client
const viemWalletClient = createWalletClient({
account: privateKeyToAccount('0x...'), // or use any other viem account
transport: http('https://eth-mainnet.g.alchemy.com/v2/demo'),
chain: mainnet,
});
// Setup viem wallet client in paygo client
await client.setViemWalletClient(viemWalletClient);
// Request tokens from faucet to viem signer's address
const faucetRequestViem = new FaucetRequest(1000000000000000000n); // amount in cents
const faucetResponseViem = await client.signAndPostTransactionFromParams(faucetRequestViem, SignerConfig.Viem);
console.log(`Faucet request sent: ${faucetResponseViem.hash}`);
// Request tokens from faucet to local signer's address
const faucetRequestLocal = new FaucetRequest(1000000000000000000n); // amount in cents
const faucetResponseLocal = await client.signAndPostTransactionFromParams(faucetRequestLocal, SignerConfig.Local);
console.log(`Faucet request sent: ${faucetResponseLocal.hash}`);