Skip to main content

Quote Builder

The QuoteBuilder module enables providers to create signed price quotes per AIP-2 specification.


Overview

QuoteBuilder provides:

  • Price quote construction with validation
  • EIP-712 signature generation
  • Canonical JSON hashing
  • Optional IPFS upload for quote storage

Quote Message Structure

Per AIP-2 specification:

// Level 2: Advanced API - Direct protocol control
interface QuoteMessage {
type: 'agirails.quote.v1';
version: '1.0.0';
txId: string; // Transaction ID (bytes32)
provider: string; // Provider DID
consumer: string; // Consumer DID
quotedAmount: string; // Provider's quoted price
originalAmount: string; // Consumer's original offer
maxPrice: string; // Consumer's maximum
currency: string; // "USDC"
decimals: number; // 6 for USDC
quotedAt: number; // Unix timestamp
expiresAt: number; // Expiration timestamp
justification?: {
reason?: string;
estimatedTime?: number;
computeCost?: number;
breakdown?: Record<string, any>;
};
chainId: number;
nonce: number;
signature: string; // EIP-712 signature
}

Methods

build()

Build and sign a price quote.

// Level 2: Advanced API - Direct protocol control
import { QuoteBuilder, NonceManager } from '@agirails/sdk';

const nonceManager = new NonceManager('.actp/nonces');
const quoteBuilder = new QuoteBuilder(signer, nonceManager);

const quote = await quoteBuilder.build({
txId: '0x...',
provider: 'did:ethr:84532:0xProvider...',
consumer: 'did:ethr:84532:0xConsumer...',
quotedAmount: '7500000', // $7.50 USDC
originalAmount: '5000000', // $5.00 original
maxPrice: '10000000', // $10.00 max
expiresAt: Math.floor(Date.now() / 1000) + 3600, // 1 hour
justification: {
reason: 'Complex analysis required',
estimatedTime: 300, // 5 minutes
computeCost: 2500000, // $2.50
},
chainId: 84532,
kernelAddress: KERNEL_ADDRESS,
});

console.log('Quote:', quote);
console.log('Signature:', quote.signature);

Parameters:

ParameterTypeDescription
txIdstringTransaction ID
providerstringProvider DID
consumerstringConsumer DID
quotedAmountstringQuoted price (base units)
originalAmountstringOriginal offer amount
maxPricestringMaximum acceptable price
currencystring?Currency code (default: "USDC")
decimalsnumber?Token decimals (default: 6)
expiresAtnumber?Expiry timestamp (default: +1 hour)
justificationobject?Optional price justification
chainIdnumberNetwork chain ID
kernelAddressstringKernel contract address

verify()

Verify a quote signature.

// Level 2: Advanced API - Direct protocol control
const isValid = await quoteBuilder.verify(quote);

if (isValid) {
console.log('Quote signature is valid');
} else {
console.log('Invalid signature - reject quote');
}

hash()

Get the canonical hash of a quote (for storage/lookup).

// Level 2: Advanced API - Direct protocol control
const quoteHash = quoteBuilder.hash(quote);
console.log('Quote hash:', quoteHash);

Validation Rules

QuoteBuilder enforces these rules:

RuleDescription
Amount boundsquotedAmount >= originalAmount
Max pricequotedAmount <= maxPrice
ExpiryexpiresAt > quotedAt
Valid addressesAll addresses are valid Ethereum format
Valid DIDsProvider/consumer are valid DID format

Quote Flow

Quote Flow Sequence Diagram

Example: Provider Quote Response

// Level 2: Advanced API - Direct protocol control
import { QuoteBuilder, NonceManager } from '@agirails/sdk';

class PricingService {
private quoteBuilder: QuoteBuilder;

constructor(signer: Signer, stateDir: string) {
const nonceManager = new NonceManager(stateDir);
this.quoteBuilder = new QuoteBuilder(signer, nonceManager);
}

async generateQuote(request: {
txId: string;
consumer: string;
originalAmount: string;
maxPrice: string;
complexity: 'low' | 'medium' | 'high';
}) {
// Calculate price based on complexity
const basePrice = BigInt(request.originalAmount);
const multipliers = { low: 1n, medium: 2n, high: 3n };
const quotedAmount = basePrice * multipliers[request.complexity];

// Ensure within max price
const maxPrice = BigInt(request.maxPrice);
const finalAmount = quotedAmount > maxPrice ? maxPrice : quotedAmount;

// Build signed quote
const quote = await this.quoteBuilder.build({
txId: request.txId,
provider: 'did:ethr:84532:0x...',
consumer: request.consumer,
quotedAmount: finalAmount.toString(),
originalAmount: request.originalAmount,
maxPrice: request.maxPrice,
justification: {
reason: `${request.complexity} complexity task`,
estimatedTime: request.complexity === 'high' ? 600 : 120,
},
chainId: 84532,
kernelAddress: KERNEL_ADDRESS,
});

return quote;
}
}

EIP-712 Types

QuoteBuilder uses these EIP-712 types:

// Level 2: Advanced API - Direct protocol control
const AIP2QuoteTypes = {
PriceQuote: [
{ name: 'txId', type: 'bytes32' },
{ name: 'provider', type: 'string' },
{ name: 'consumer', type: 'string' },
{ name: 'quotedAmount', type: 'string' },
{ name: 'originalAmount', type: 'string' },
{ name: 'maxPrice', type: 'string' },
{ name: 'currency', type: 'string' },
{ name: 'decimals', type: 'uint8' },
{ name: 'quotedAt', type: 'uint256' },
{ name: 'expiresAt', type: 'uint256' },
{ name: 'justificationHash', type: 'bytes32' },
{ name: 'chainId', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
],
};

Next Steps