You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: bip70.md
+60-2
Original file line number
Diff line number
Diff line change
@@ -9,5 +9,63 @@ Since RBF payments can be modified after they are broadcast, they will also be r
9
9
*`required_fee_rate` - The minimum fee per byte required on your transaction. Bitcoin Cash payments will be rejected if fee rate included for the transaction is not at least this value. _May be fractional value_ ie 0.123 sat/byte
10
10
11
11
## Application Logic
12
-
Please note that you should **NOT** broadcast a payment to the P2P network if we respond with an http status code other than `200`. Broadcasting a payment before getting a success notification back from the server will
13
-
lead to a failed payment for the sender. The sender will bear the cost of paying transaction fees yet again to get their money back.
12
+
13
+
Since rejecting invalid payments before they are broadcast to the network is a primary goal of payment protocol, we recommend following this
4. Send the unsigned transaction and weighed size of the signed transaction to the server (**bitpay specific**)
20
+
5. If server rejects at this point, do not continue. Otherwise, send via standard payment protocol and broadcast to p2p in parallel
21
+
22
+
Please note that you should **NOT** broadcast a payment to the P2P network if we respond with an http status code other than `200` in
23
+
the verification step. Broadcasting a payment before getting a success notification back from the server will lead to a failed payment
24
+
for the sender. The sender will bear the cost of paying transaction fees yet again to get their money back.
25
+
26
+
## Payment Request
27
+
28
+
### Request
29
+
A GET request should be made to the payment protocol url.
30
+
31
+
### Response
32
+
The response will payload identical to the BIP70 format with one additional field for `required_fee_rate`.
33
+
34
+
#### Headers
35
+
On a successful request, the response will contain the standard BIP-70 headers.
36
+
37
+
38
+
## Payment Verification
39
+
40
+
### Request
41
+
A POST request should be made to the payment protocol url with the header `application/bitcoin-verify-payment` or `application/bitcoincash-verify-payment`.
42
+
43
+
### Request Body
44
+
The body should contain the **unsigned** transaction as well as the weighted size in vbytes of the fully signed transaction. Weighted size
45
+
really only applies for transactions with segwit inputs, if you have a non-segwit transaction the byte size is the correct value to send.
46
+
With bitcoin core this is simply the vsize value of a transaction. If you're not certain about calculating the weighted size, please see
47
+
the [bitcoin documentation about it](https://en.bitcoin.it/wiki/Weight_units). The format of this request should be based on this protobuf
48
+
proto:
49
+
```
50
+
message PaymentVerification {
51
+
required bytes unsigned_transaction = 1;
52
+
required uint64 weighted_size = 2 [default = 0];
53
+
}
54
+
```
55
+
56
+
### Response
57
+
A 200 status code will be returned for valid payments, all other status codes will return with an error message stating why the payment was rejected.
58
+
59
+
60
+
## Payment
61
+
62
+
### Request
63
+
A POST request should be made to the payment protocol url with the standard BIP-70 payment header (`application/bitcoin-payment` or `application/bitcoincash-payment`)
64
+
65
+
### Request Body
66
+
The body should contain the **signed** transaction in BIP-70 format
67
+
68
+
### Response
69
+
A 200 status code will be returned for valid payments, all other status codes will return with an error message stating why the payment was rejected.
Copy file name to clipboardexpand all lines: readme.md
+51-31
Original file line number
Diff line number
Diff line change
@@ -30,16 +30,28 @@ paymentProtocol.getRawPaymentRequest(requestUrl, function (err, response) {
30
30
console.log(paymentRequest);
31
31
32
32
//TODO: Create the rawTransaction and sign it in your wallet instead of this, do NOT broadcast yet
33
-
let currency ='BTC'
34
-
let signedRawTransaction ='02000000010c2b0d60448d5cdfebe222014407bdb408b8427f837447484911efddea700323000000006a47304402201d3ed3117f1968c3b0a078f15f8462408c745ff555b173eff3dfe0a25e063c0c02200551572ec33d45ece8e64275970bd1b1694621f0ed8fac2f7e18095f170fe3fe012102d4edb773e3bd94e1251790f5cc543cbfa76c2b0abad14898674b1c4e27176ef2ffffffff02c44e0100000000001976a914dd826377dcf2075e5065713453cfad675ba9434f88aca070002a010000001976a914e7d0344ba970301e93cd7b505c7ae1b5bcf5639288ac00000000';
let unsignedRawTransaction ='02000000016b7bceefa3ff3bf6f3ad39a99cf6def9126a6edf8f49462bd06e4cb74366dab00100000000feffffff0248590095000000001976a9141b4f4e0c5354ce950ea702cc79be34885e7a60af88ac0c430100000000001976a914072053b485736e002f665d5fc65c443fb379256e88ac00000000'
37
+
// Signed version of that transaction
38
+
let signedRawTransaction ='02000000016b7bceefa3ff3bf6f3ad39a99cf6def9126a6edf8f49462bd06e4cb74366dab0010000006b4830450221008d8852576eb8e505832a53569dd756a1d0c304606c27e81d0ac1a83e78250969022058b2bde3f2e1ea7e6a62e69d99f7219e846f04c1c58ff163e2996669a935c31501210206e855c3cfd24a5e154cf94ff7a214d598dfc2d62966011fd83c360cf229777ffeffffff0248590095000000001976a9141b4f4e0c5354ce950ea702cc79be34885e7a60af88ac0c430100000000001976a914072053b485736e002f665d5fc65c443fb379256e88ac00000000';
39
+
// total size of the signed transaction (note the way shown here is incorrect for segwit, see the code in /examples for getting vsize from RPC)
40
+
let signedRawTransactionSize =Buffer.from(signedRawTransaction, 'hex').byteLength;
//TODO: Create the rawTransaction and sign it in your wallet instead of this, do NOT broadcast yet
64
-
let currency ='BTC'
65
-
let signedRawTransaction ='02000000010c2b0d60448d5cdfebe222014407bdb408b8427f837447484911efddea700323000000006a47304402201d3ed3117f1968c3b0a078f15f8462408c745ff555b173eff3dfe0a25e063c0c02200551572ec33d45ece8e64275970bd1b1694621f0ed8fac2f7e18095f170fe3fe012102d4edb773e3bd94e1251790f5cc543cbfa76c2b0abad14898674b1c4e27176ef2ffffffff02c44e0100000000001976a914dd826377dcf2075e5065713453cfad675ba9434f88aca070002a010000001976a914e7d0344ba970301e93cd7b505c7ae1b5bcf5639288ac00000000';
let response =awaitpaymentProtocol.getRawPaymentRequestAsync(requestUrl);
67
+
let paymentRequest =awaitpaymentProtocol.parsePaymentRequestAsync(response.rawBody, response.headers);
68
+
69
+
console.log('Payment request retrieved');
70
+
console.log(paymentRequest);
71
+
72
+
//TODO: Create the rawTransaction and sign it in your wallet instead of this example, do NOT broadcast yet
73
+
// Funded unsigned raw transaction
74
+
let unsignedRawTransaction ='02000000016b7bceefa3ff3bf6f3ad39a99cf6def9126a6edf8f49462bd06e4cb74366dab00100000000feffffff0248590095000000001976a9141b4f4e0c5354ce950ea702cc79be34885e7a60af88ac0c430100000000001976a914072053b485736e002f665d5fc65c443fb379256e88ac00000000'
75
+
// Signed version of that transaction
76
+
let signedRawTransaction ='02000000016b7bceefa3ff3bf6f3ad39a99cf6def9126a6edf8f49462bd06e4cb74366dab0010000006b4830450221008d8852576eb8e505832a53569dd756a1d0c304606c27e81d0ac1a83e78250969022058b2bde3f2e1ea7e6a62e69d99f7219e846f04c1c58ff163e2996669a935c31501210206e855c3cfd24a5e154cf94ff7a214d598dfc2d62966011fd83c360cf229777ffeffffff0248590095000000001976a9141b4f4e0c5354ce950ea702cc79be34885e7a60af88ac0c430100000000001976a914072053b485736e002f665d5fc65c443fb379256e88ac00000000';
77
+
// total size of the signed transaction (note the way shown here is incorrect for segwit, see the code in /examples for getting vsize from RPC)
78
+
let signedRawTransactionSize =Buffer.from(signedRawTransaction, 'hex').byteLength;
79
+
80
+
// This sends the proposed unsigned transaction to the server
0 commit comments