Skip to content

paymentOptions and contracts need the same keys.... #9

Description

@a6b8
const config = {
    'silent': false,
    'envPath': './../.via402.env',
    'snowtraceAddressBaseUrl': 'https://testnet.snowtrace.io/address',
    'envSelection': [
        [ 'facilitatorPublicKey',  'X402_FACILITATOR_PUBLIC_KEY'   ],
        [ 'facilitatorPrivateKey', 'X402_FACILITATOR_PRIVATE_KEY'  ],
        [ 'recepientAddress',      'X402_RECEPIENT_PUBLIC_KEY'     ],
        [ 'serverProviderUrl',     'X402_FUJI_PROVIDER_URL'        ],
        [ 'DUNE_SIM_API_KEY',      'DUNE_SIM_API_KEY'              ]
    ],
    'arrayOfRoutes': [ 
        {  
            'includeNamespaces': [], 
            'routePath': '/mcp', 
            'protocol': 'streamable' 
        } 
    ],
    'x402': {
        'routePath': '/mcp',
        'chainId': 43113,
        'chainName': 'avax_fuji',
        'restrictedCalls': [
            {
                'method': 'tools/call',
                'name': 'paid_ping_x402',
                'activePaymentOptions': [ 'usdc-fuji-cheap' ],
            },
            {
                'method': 'tools/call',
                'name': 'getActivityEVM_avax',
                'activePaymentOptions': [ 'usdc-fuji-standard' ],
            },
            {
                'method': 'tools/call',
                'name': 'getTokenHoldersEVM_avax',
                'activePaymentOptions': [ 'usdc-fuji-premium' ],
            },
            {
                'method': 'tools/call',
                'name': 'getCollectiblesEVM_avax',
                'activePaymentOptions': [ 'usdc-fuji-standard' ],
            }
        ], 
        'paymentOptions': {
            'usdc-fuji-cheap': { 
                'contractId': 'usdc-fuji',
                'maxAmountRequired': '0.0001',
                'payTo': '{{recepientAddress}}',
            },
            'usdc-fuji-standard': { 
                'contractId': 'usdc-fuji',
                'maxAmountRequired': '0.005',
                'payTo': '{{recepientAddress}}',
            },
            'usdc-fuji-premium': { 
                'contractId': 'usdc-fuji',
                'maxAmountRequired': '0.0777',
                'payTo': '{{recepientAddress}}',
            }
        },
        'contracts': {
            'usdc-fuji': {
                'domainName': 'USDC',
                'address': '0x5425890298aed601595a70AB815c96711a31Bc65',
                'assetType': 'erc20',
                'decimals': 6
            }
        }
    }
}


function bugFixContractIds( { paymentOptions, contracts } ) {
    const contractsWithAliases = Object
        .keys( paymentOptions )
        .reduce( ( acc, paymentOptionId ) => {
            const baseId = paymentOptions[ paymentOptionId ].contractId
            if( baseId && contracts[ baseId ] ) {
                acc[ paymentOptionId ] = contracts[ baseId ]
            }
            return acc
        }, { ...contracts } )

    return { contractsWithAliases }
}

The root bug is in the upstream modules x402-core (specifically ServerExact.getPaymentRequirementsPayload) and the calling
path in x402-mcp-middleware: for each payment option, the option key (e.g., usdc-fuji-cheap) is used to look up the
contract in contracts. If contracts only contains usdc-fuji, contract is undefined and the destructuring crashes.

const contractsWithAliases = bugFixContractIds( { paymentOptions, contracts } )
const middleware = await X402Middleware
    .create( { chainId, chainName, contracts: contractsWithAliases, paymentOptions, restrictedCalls, x402Credentials, x402PrivateKey } )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions