Permaweb Payment Protocol
Goal
Describe a protocol that enables payment channels to incentivize a variety services in the Arweave ecosystem.
Mechanism Design
- Clients enumerate available service providers.
- Clients request service prices from providers.
- Clients make deposits at cheapest and most responsive service providers.
- Clients make service requests to providers holding deposits.
- Service providers charge service fees against the clients deposit.
- Clients score service providers based on reliability and responsiveness.
- Service providers compete on price, reliability, and responsiveness to serve clients.
Rates
Service providers may publish their services and corresponding rates via the rates endpoint.
GET
The following is an example response body from the /rates
endpoint.
{
"endpoints": [ {
"endpoint":"/graphql",
"modSeq": 1,
"rates": {
"description": "Price per block queried",
"arweave": {
"AR": {
"price":"10000",
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
},
"VRT": {
"price":"1",
"contractId":"aLemOhg9OGovn-0o4cOCbueiHT9VgdYnpJpq7NgMA1A",
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
}
},
"external": {
"url":"https://example.com/deposit.html"
},
"polygon": {
"MATIC": {
"price":"11010101",
"address": "0x0e2Db4C482B9fd5809f5bF48d04A3eE1a9D73D96"
}
},
"solana": {
"SOL": {
"price":"111101010",
"address":"ApFWL3dtpFX8tU15uPzWnvfeQRtompvoAs9DNEnQH6DL"
}
}
}
}, {
"endpoint":"/tx/{id}/{field}",
"modSeq": 3,
"rates": {
"description": "Price per request",
"arweave": {
"AR": {
"price":"10000",
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
}
}
}
}, {
"endpoint":"/tx/{id}",
"modSeq": 1,
"rates": {
"description": "Price per request",
"arweave": {
"AR": {
"price":"10000",
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
}
}
}
},{
"endpoint":"/chunk/{offset}",
"modSeq": 5,
"rates": {
"description": "Price per byte of data",
"arweave": {
"price":"100000",
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
}
}
}, {
"endpoint":"/{txid}",
"modSeq": 2,
"rates": {
"arweave": {
"price":"100000",
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
}
}
}]
}
Schema
The root object contains an array of Service Endpoint Config
, each one representing the pricing and metadata for a particular service endpoint.
{
"endpoints": [ … ]
}
Service Endpoint Config
Each element of the endpoints
array is an instance of a Service Endpoint Config
. Each config describes the HTTP API service endpoint along service rates (cost).
{
"endpoint":"/graphql",
"modSeq": 1,
"rates": { … }
}
Property | Required | Description |
---|---|---|
endpoint | required | The path to the endpoint that is providing service. |
modSeq | required | The modification sequence number for the endpoint config. Enables clients to cache rates for an endpoint and be directed to requery rates only when the underlying rates are updated. |
rates | required | A Rates Config object describing the prices for service at this endpoint. |
Rates Config
Each Service Endpoint Config
publishes an array of Rates Config
to describe service pricing. Rate Configs
allow for prices to be listed in a variety of network tokens, provided the service operator maintains a wallet native to that network.
"rates": {
"description": "Price per block queried",
"arweave": { … },
"polygon": { … },
"solana": { … }
}
Network Price Config
Describes the price of service denominated in a token native to the network. Also provides the wallet address to transfer tokens to in order to fun a deposit.
"arweave": {
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
"AR": {
"price":"10000",
},
"VRT": {
"price":"1",
"contractId":"aLemOhg9OGovn-0o4cOCbueiHT9VgdYnpJpq7NgMA1A",
"address":"89tR0-C1m3_sCWCoVCChg4gFYKdiH5_ZDyZpdJ2DDRw"
}
},
In this example the arweave Network Price Config supports payment in the native token AR as well as a PST token VRT. VRT is managed by a smartweave contract so that contractId
is listed as well. For each token the corresponding price for service is listed.
Property | Description |
---|---|
price | The cost of service (described in the Rates Config description property).In the case of arweave, the price is delineated in Winstons (atomic units). |
address | The wallet address to receive the service payment. |
contractId | In the case of a token managed by a smart contract like a PST or ERC-20, this specifies the contract ID. |
price
is always denominated in the smallest divisible unit of the token, otherwise known as atomic unitsExternal Price Config
For “off chain” value transfers (like credit card payments or other incentivized channels) the price config simply provides a URL of a page to make the payment.
"external": {
"url":"https://example.com/deposit.html"
},
Service Requests
Requesting service from a Permaweb Payments Protocol (P3) endpoint follows a standard HTTP API request format. However, to properly identify which wallet to charge for the service, requests must also include some P3 specific HTTP headers.
Request Headers
Header | Required | Description |
---|---|---|
anchor | (optional) | Nonce that can be optionally provided and optionally implemented by the service endpoint to prevent replay attacks. |
modSeq | (optional) | The caller can specify the modSeq of the Endpoint Config they have cached locally and are expecting to be charged. |
price | (optional) | The <network>/<token> of the Price Config to use. Defaults to arweave/AR . |
timeout | (optional) | Number of milliseconds the client will wait before timing out the request. This enables clients to indicate a willingness to wait longer for responses when the data is important (and not score the provider poorly as a result) |
endpoint | required | The value of the endpoint field in the ServiceEndpointConfig e.g. "/graphql" |
address | required | The wallet address of the deposit to charge for service. |
signature | required | The request headers endpoint + address + modSeq + price + anchor + timeout are concatenated, SHA-256 hashed and the hash is signed by the private key of the wallet indicated by address . (if optional parameters are missing they are dropped) |
HTTP Response Codes
Code | Description |
---|---|
🟢 200 | OK |
🔴 400 | Bad Request - invalid P3 headers/header values |
🔴 402 | Bad Request - Payment Required - Not enough funds on deposit |
🟡 428 | Precondition Required - modSeq is out of date |
🟡 429 | Too many requests - and/or Rate limited |
Response Headers
When the service endpoint responds with data, it will include the following HTTP headers in the response.
Deposits
By default any wallet posting a “deposit” transaction to an address specified by a Price Config will be credited with the deposit and able to sign P3 request headers to bill against it.
Optionally, a deposit transaction may specify an array of wallet entries to be credited with a portion of the deposit. This is accomplished by adding a “addresses” Custom Tag to the transaction with the following entry format, a JSON array of {<address>:<amount>}
entries.
"addresses": “[
{ "79pOFCwHmdgiqcl6blGFY45eS87V-OkiPspLvRCrRq4" : 100 },
{ "NoHbaZ9ZchidleZNdHYHb2TFV4puCBJTiESZ07dPXJg" : 50 },
{ "xo6_3x3pdVnRc6fKPduoUtK3M3ABF2-V7iUilHMCy3I" : 50 }
]”
If the total of the amount
values does not exactly match the number of tokens being deposited, then the amount
‘s will be averaged and the deposit split amongst the wallets proportionally.
In the case where a wallets
list is provided, the owner of the transaction must include their own wallet address in the wallets
list if they wish it to be credited with a portion of the deposit.
Balances
Enables clients to check their balance with a given service provider to verify pricing and determine when to "top up" their deposit.
GET
Note: While Rate Configs are unique to each service endpoint, the balance on deposit for a given wallet address is shared across all service endpoints. There is no protocol defined means to limit deposits to a single service endpoint. If the provider has a deposit for the client wallet it will bill against that deposit regardless of what service is requested.
Charging for Service
When a gateway bills a client for service, it deducts that amount from the local deposit ledger it maintains for client addresses. This way the gateway can more efficiently rollup fees to a single transaction at day's end, or whatever interval makes sense for the gateway operator.
As long as the Balance endpoint is accurate, this should be sufficient for clients.