diff --git a/x402.go b/x402.go index 92b6e80..a85b565 100644 --- a/x402.go +++ b/x402.go @@ -33,40 +33,6 @@ func createNonce() (string, error) { return "0x" + common.Bytes2Hex(nonce), nil } -// BlockRunServiceCode is BlockRun's x402 builder code — the ERC-8021 Schema 2 -// service code (s) that tags every payment this SDK signs as BlockRun-originated -// for on-chain attribution. -// See https://docs.cdp.coinbase.com/x402/core-concepts/builder-codes -const BlockRunServiceCode = "blockrun" - -// withBuilderCodeServiceCode merges BlockRun's service code (s) into the -// payload's builder-code extension, preserving any app code (a) the server -// echoed back in its 402. The CDP facilitator reads builder-code.info.s and -// encodes it into the settlement calldata suffix — no CBOR happens client-side. -func withBuilderCodeServiceCode(extensions map[string]any) map[string]any { - merged := map[string]any{} - for k, v := range extensions { - merged[k] = v - } - - builderCode := map[string]any{} - info := map[string]any{} - if bc, ok := merged["builder-code"].(map[string]any); ok { - for k, v := range bc { - builderCode[k] = v - } - if existingInfo, ok := bc["info"].(map[string]any); ok { - for k, v := range existingInfo { - info[k] = v - } - } - } - info["s"] = []string{BlockRunServiceCode} - builderCode["info"] = info - merged["builder-code"] = builderCode - return merged -} - // CreatePaymentPayload creates a signed x402 v2 payment payload. // // This uses EIP-712 typed data signing to create a payment authorization @@ -213,7 +179,7 @@ func CreatePaymentPayload( Nonce: nonce, }, }, - Extensions: withBuilderCodeServiceCode(extensions), + Extensions: extensions, } // Encode as JSON then base64 diff --git a/x402_test.go b/x402_test.go deleted file mode 100644 index cb3c38c..0000000 --- a/x402_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package blockrun - -import ( - "encoding/base64" - "encoding/json" - "testing" -) - -func decodeServiceCodeInfo(t *testing.T, payload string) map[string]any { - t.Helper() - decoded, err := base64.StdEncoding.DecodeString(payload) - if err != nil { - t.Fatalf("failed to decode payload: %v", err) - } - var pp PaymentPayload - if err := json.Unmarshal(decoded, &pp); err != nil { - t.Fatalf("failed to unmarshal payload: %v", err) - } - bc, ok := pp.Extensions["builder-code"].(map[string]any) - if !ok { - t.Fatalf("missing builder-code extension: %v", pp.Extensions) - } - info, ok := bc["info"].(map[string]any) - if !ok { - t.Fatalf("missing builder-code.info: %v", bc) - } - return info -} - -func assertServiceCode(t *testing.T, info map[string]any) { - t.Helper() - s, ok := info["s"].([]any) - if !ok || len(s) != 1 || s[0] != "blockrun" { - t.Errorf("expected service code [blockrun], got %v", info["s"]) - } -} - -func TestCreatePaymentPayloadAttachesServiceCode(t *testing.T) { - client, err := NewLLMClient(testPrivateKey) - if err != nil { - t.Fatalf("failed to create client: %v", err) - } - - payload, err := CreatePaymentPayload( - client.privateKey, - "0x1234567890123456789012345678901234567890", - "1000", - "eip155:8453", - "https://blockrun.ai/api/v1/chat/completions", - "Test payment", - 300, - nil, - nil, - ) - if err != nil { - t.Fatalf("failed to create payment payload: %v", err) - } - - assertServiceCode(t, decodeServiceCodeInfo(t, payload)) -} - -func TestCreatePaymentPayloadPreservesEchoedAppCode(t *testing.T) { - client, err := NewLLMClient(testPrivateKey) - if err != nil { - t.Fatalf("failed to create client: %v", err) - } - - extensions := map[string]any{ - "builder-code": map[string]any{ - "info": map[string]any{"a": "blockrun"}, - }, - } - - payload, err := CreatePaymentPayload( - client.privateKey, - "0x1234567890123456789012345678901234567890", - "1000", - "eip155:8453", - "https://blockrun.ai/api/v1/chat/completions", - "Test payment", - 300, - nil, - extensions, - ) - if err != nil { - t.Fatalf("failed to create payment payload: %v", err) - } - - info := decodeServiceCodeInfo(t, payload) - assertServiceCode(t, info) - if info["a"] != "blockrun" { - t.Errorf("expected echoed app code blockrun, got %v", info["a"]) - } -}