@flarcos/arazzo-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +252 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +212 -0
- package/dist/cli.js.map +1 -0
- package/dist/generated/open-payments-client.d.ts +283 -0
- package/dist/generated/open-payments-client.d.ts.map +1 -0
- package/dist/generated/open-payments-client.js +1588 -0
- package/dist/generated/open-payments-client.js.map +1 -0
- package/dist/generator/codegen.d.ts +32 -0
- package/dist/generator/codegen.d.ts.map +1 -0
- package/dist/generator/codegen.js +127 -0
- package/dist/generator/codegen.js.map +1 -0
- package/dist/generator/templates.d.ts +27 -0
- package/dist/generator/templates.d.ts.map +1 -0
- package/dist/generator/templates.js +154 -0
- package/dist/generator/templates.js.map +1 -0
- package/dist/generator/type-mapper.d.ts +35 -0
- package/dist/generator/type-mapper.d.ts.map +1 -0
- package/dist/generator/type-mapper.js +145 -0
- package/dist/generator/type-mapper.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/arazzo-parser.d.ts +38 -0
- package/dist/parser/arazzo-parser.d.ts.map +1 -0
- package/dist/parser/arazzo-parser.js +162 -0
- package/dist/parser/arazzo-parser.js.map +1 -0
- package/dist/parser/types.d.ts +115 -0
- package/dist/parser/types.d.ts.map +1 -0
- package/dist/parser/types.js +10 -0
- package/dist/parser/types.js.map +1 -0
- package/dist/runtime/expression-resolver.d.ts +59 -0
- package/dist/runtime/expression-resolver.d.ts.map +1 -0
- package/dist/runtime/expression-resolver.js +180 -0
- package/dist/runtime/expression-resolver.js.map +1 -0
- package/dist/runtime/http-client.d.ts +47 -0
- package/dist/runtime/http-client.d.ts.map +1 -0
- package/dist/runtime/http-client.js +126 -0
- package/dist/runtime/http-client.js.map +1 -0
- package/dist/runtime/types.d.ts +109 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +7 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/workflow-executor.d.ts +33 -0
- package/dist/runtime/workflow-executor.d.ts.map +1 -0
- package/dist/runtime/workflow-executor.js +506 -0
- package/dist/runtime/workflow-executor.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,1588 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open Payments Arazzo SDK — Auto-generated workflow functions
|
|
3
|
+
*
|
|
4
|
+
* Generated from Arazzo 1.0.1 workflow specifications.
|
|
5
|
+
* Do not edit manually — regenerate with: arazzo-sdk generate
|
|
6
|
+
*
|
|
7
|
+
* @generated
|
|
8
|
+
*/
|
|
9
|
+
import { executeWorkflow } from '../runtime/workflow-executor.js';
|
|
10
|
+
import { GnapAuthProvider } from '../runtime/http-client.js';
|
|
11
|
+
/**
|
|
12
|
+
* OpenPaymentsClient — typed workflow executor for Open Payments API.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const client = new OpenPaymentsClient({
|
|
17
|
+
* clientWalletAddress: 'https://wallet.example.com/me',
|
|
18
|
+
* serverUrls: {
|
|
19
|
+
* walletAddressServer: 'https://wallet.example.com',
|
|
20
|
+
* resourceServer: 'https://wallet.example.com',
|
|
21
|
+
* authServer: 'https://auth.wallet.example.com',
|
|
22
|
+
* },
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const result = await client.oneTimePaymentFixedReceive({ ... });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class OpenPaymentsClient {
|
|
29
|
+
serverUrls;
|
|
30
|
+
authProvider;
|
|
31
|
+
hooks;
|
|
32
|
+
interactionHandler;
|
|
33
|
+
constructor(options) {
|
|
34
|
+
this.serverUrls = options.serverUrls;
|
|
35
|
+
this.hooks = options.hooks;
|
|
36
|
+
this.interactionHandler = options.interactionHandler;
|
|
37
|
+
if (options.authProvider) {
|
|
38
|
+
this.authProvider = options.authProvider;
|
|
39
|
+
}
|
|
40
|
+
else if (options.gnapConfig) {
|
|
41
|
+
this.authProvider = new GnapAuthProvider(options.gnapConfig);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Set the GNAP access token for a source.
|
|
46
|
+
* Call this after obtaining tokens from grant requests.
|
|
47
|
+
*/
|
|
48
|
+
setToken(sourceName, token) {
|
|
49
|
+
if (this.authProvider && 'setToken' in this.authProvider) {
|
|
50
|
+
this.authProvider.setToken(sourceName, token);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* List all incoming payments on a wallet address
|
|
55
|
+
*/
|
|
56
|
+
async listIncomingPayments(inputs) {
|
|
57
|
+
const workflow = {
|
|
58
|
+
"workflowId": "listIncomingPayments",
|
|
59
|
+
"summary": "List all incoming payments on a wallet address",
|
|
60
|
+
"description": "Obtain a grant and list incoming payments with pagination support.\n",
|
|
61
|
+
"inputs": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"required": [
|
|
64
|
+
"walletAddressUrl",
|
|
65
|
+
"clientWalletAddress"
|
|
66
|
+
],
|
|
67
|
+
"properties": {
|
|
68
|
+
"walletAddressUrl": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"description": "The wallet address to list incoming payments for"
|
|
71
|
+
},
|
|
72
|
+
"clientWalletAddress": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"description": "The client's wallet address for GNAP identification"
|
|
75
|
+
},
|
|
76
|
+
"first": {
|
|
77
|
+
"type": "integer",
|
|
78
|
+
"description": "Number of results to return (forward pagination)"
|
|
79
|
+
},
|
|
80
|
+
"cursor": {
|
|
81
|
+
"type": "string",
|
|
82
|
+
"description": "Pagination cursor from a previous response"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"steps": [
|
|
87
|
+
{
|
|
88
|
+
"stepId": "getWalletAddress",
|
|
89
|
+
"description": "Resolve the wallet address to discover auth and resource server URLs.\n",
|
|
90
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
91
|
+
"successCriteria": [
|
|
92
|
+
{
|
|
93
|
+
"condition": "$statusCode == 200"
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"outputs": {
|
|
97
|
+
"authServer": "$response.body.authServer",
|
|
98
|
+
"resourceServer": "$response.body.resourceServer"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"stepId": "requestIncomingPaymentListGrant",
|
|
103
|
+
"description": "Request a non-interactive grant with `list` permissions for incoming payments.\n",
|
|
104
|
+
"operationId": "authServer.post-request",
|
|
105
|
+
"requestBody": {
|
|
106
|
+
"contentType": "application/json",
|
|
107
|
+
"payload": {
|
|
108
|
+
"access_token": {
|
|
109
|
+
"access": [
|
|
110
|
+
{
|
|
111
|
+
"type": "incoming-payment",
|
|
112
|
+
"actions": [
|
|
113
|
+
"list"
|
|
114
|
+
],
|
|
115
|
+
"identifier": "$inputs.walletAddressUrl"
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
"client": "$inputs.clientWalletAddress"
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"successCriteria": [
|
|
123
|
+
{
|
|
124
|
+
"condition": "$statusCode == 200"
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
"outputs": {
|
|
128
|
+
"accessToken": "$response.body.access_token.value"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"stepId": "listIncomingPayments",
|
|
133
|
+
"description": "List incoming payments on the wallet address. Supports forward and backward pagination via cursor parameters.\n",
|
|
134
|
+
"operationId": "resourceServer.list-incoming-payments",
|
|
135
|
+
"parameters": [
|
|
136
|
+
{
|
|
137
|
+
"name": "wallet-address",
|
|
138
|
+
"in": "query",
|
|
139
|
+
"value": "$inputs.walletAddressUrl"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "first",
|
|
143
|
+
"in": "query",
|
|
144
|
+
"value": "$inputs.first"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"name": "cursor",
|
|
148
|
+
"in": "query",
|
|
149
|
+
"value": "$inputs.cursor"
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"successCriteria": [
|
|
153
|
+
{
|
|
154
|
+
"condition": "$statusCode == 200"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"outputs": {
|
|
158
|
+
"incomingPayments": "$response.body.result",
|
|
159
|
+
"paginationStartCursor": "$response.body.pagination.startCursor",
|
|
160
|
+
"paginationEndCursor": "$response.body.pagination.endCursor",
|
|
161
|
+
"hasNextPage": "$response.body.pagination.hasNextPage",
|
|
162
|
+
"hasPreviousPage": "$response.body.pagination.hasPreviousPage"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
],
|
|
166
|
+
"outputs": {
|
|
167
|
+
"incomingPayments": "$steps.listIncomingPayments.outputs.incomingPayments",
|
|
168
|
+
"nextCursor": "$steps.listIncomingPayments.outputs.paginationEndCursor",
|
|
169
|
+
"hasNextPage": "$steps.listIncomingPayments.outputs.hasNextPage"
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
const result = await executeWorkflow(workflow, {
|
|
173
|
+
inputs: inputs,
|
|
174
|
+
serverUrls: this.serverUrls,
|
|
175
|
+
authProvider: this.authProvider,
|
|
176
|
+
hooks: this.hooks,
|
|
177
|
+
interactionHandler: this.interactionHandler,
|
|
178
|
+
});
|
|
179
|
+
if (!result.success) {
|
|
180
|
+
throw new Error(`Workflow "listIncomingPayments" failed: ${result.error || 'Unknown error'}`);
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
...result.outputs,
|
|
184
|
+
_raw: result,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* List all outgoing payments on a wallet address
|
|
189
|
+
*/
|
|
190
|
+
async listOutgoingPayments(inputs) {
|
|
191
|
+
const workflow = {
|
|
192
|
+
"workflowId": "listOutgoingPayments",
|
|
193
|
+
"summary": "List all outgoing payments on a wallet address",
|
|
194
|
+
"description": "Obtain a grant and list outgoing payments with pagination support.\n",
|
|
195
|
+
"inputs": {
|
|
196
|
+
"type": "object",
|
|
197
|
+
"required": [
|
|
198
|
+
"walletAddressUrl",
|
|
199
|
+
"clientWalletAddress"
|
|
200
|
+
],
|
|
201
|
+
"properties": {
|
|
202
|
+
"walletAddressUrl": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"description": "The wallet address to list outgoing payments for"
|
|
205
|
+
},
|
|
206
|
+
"clientWalletAddress": {
|
|
207
|
+
"type": "string",
|
|
208
|
+
"description": "The client's wallet address for GNAP identification"
|
|
209
|
+
},
|
|
210
|
+
"first": {
|
|
211
|
+
"type": "integer",
|
|
212
|
+
"description": "Number of results to return"
|
|
213
|
+
},
|
|
214
|
+
"cursor": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"description": "Pagination cursor"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
"steps": [
|
|
221
|
+
{
|
|
222
|
+
"stepId": "getWalletAddress",
|
|
223
|
+
"description": "Resolve the wallet address to discover server URLs.\n",
|
|
224
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
225
|
+
"successCriteria": [
|
|
226
|
+
{
|
|
227
|
+
"condition": "$statusCode == 200"
|
|
228
|
+
}
|
|
229
|
+
],
|
|
230
|
+
"outputs": {
|
|
231
|
+
"authServer": "$response.body.authServer",
|
|
232
|
+
"resourceServer": "$response.body.resourceServer"
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"stepId": "requestOutgoingPaymentListGrant",
|
|
237
|
+
"description": "Request a non-interactive grant with `list` permissions for outgoing payments.\n",
|
|
238
|
+
"operationId": "authServer.post-request",
|
|
239
|
+
"requestBody": {
|
|
240
|
+
"contentType": "application/json",
|
|
241
|
+
"payload": {
|
|
242
|
+
"access_token": {
|
|
243
|
+
"access": [
|
|
244
|
+
{
|
|
245
|
+
"type": "outgoing-payment",
|
|
246
|
+
"actions": [
|
|
247
|
+
"list"
|
|
248
|
+
],
|
|
249
|
+
"identifier": "$inputs.walletAddressUrl"
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
"client": "$inputs.clientWalletAddress"
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
"successCriteria": [
|
|
257
|
+
{
|
|
258
|
+
"condition": "$statusCode == 200"
|
|
259
|
+
}
|
|
260
|
+
],
|
|
261
|
+
"outputs": {
|
|
262
|
+
"accessToken": "$response.body.access_token.value"
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"stepId": "listOutgoingPayments",
|
|
267
|
+
"description": "List outgoing payments on the wallet address with pagination.\n",
|
|
268
|
+
"operationId": "resourceServer.list-outgoing-payments",
|
|
269
|
+
"parameters": [
|
|
270
|
+
{
|
|
271
|
+
"name": "wallet-address",
|
|
272
|
+
"in": "query",
|
|
273
|
+
"value": "$inputs.walletAddressUrl"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"name": "first",
|
|
277
|
+
"in": "query",
|
|
278
|
+
"value": "$inputs.first"
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"name": "cursor",
|
|
282
|
+
"in": "query",
|
|
283
|
+
"value": "$inputs.cursor"
|
|
284
|
+
}
|
|
285
|
+
],
|
|
286
|
+
"successCriteria": [
|
|
287
|
+
{
|
|
288
|
+
"condition": "$statusCode == 200"
|
|
289
|
+
}
|
|
290
|
+
],
|
|
291
|
+
"outputs": {
|
|
292
|
+
"outgoingPayments": "$response.body.result",
|
|
293
|
+
"paginationEndCursor": "$response.body.pagination.endCursor",
|
|
294
|
+
"hasNextPage": "$response.body.pagination.hasNextPage"
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
],
|
|
298
|
+
"outputs": {
|
|
299
|
+
"outgoingPayments": "$steps.listOutgoingPayments.outputs.outgoingPayments",
|
|
300
|
+
"nextCursor": "$steps.listOutgoingPayments.outputs.paginationEndCursor",
|
|
301
|
+
"hasNextPage": "$steps.listOutgoingPayments.outputs.hasNextPage"
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const result = await executeWorkflow(workflow, {
|
|
305
|
+
inputs: inputs,
|
|
306
|
+
serverUrls: this.serverUrls,
|
|
307
|
+
authProvider: this.authProvider,
|
|
308
|
+
hooks: this.hooks,
|
|
309
|
+
interactionHandler: this.interactionHandler,
|
|
310
|
+
});
|
|
311
|
+
if (!result.success) {
|
|
312
|
+
throw new Error(`Workflow "listOutgoingPayments" failed: ${result.error || 'Unknown error'}`);
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
...result.outputs,
|
|
316
|
+
_raw: result,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Get details of a specific incoming or outgoing payment
|
|
321
|
+
*/
|
|
322
|
+
async getPaymentDetails(inputs) {
|
|
323
|
+
const workflow = {
|
|
324
|
+
"workflowId": "getPaymentDetails",
|
|
325
|
+
"summary": "Get details of a specific incoming or outgoing payment",
|
|
326
|
+
"description": "Retrieve the current state of a specific payment resource by its ID.\n",
|
|
327
|
+
"inputs": {
|
|
328
|
+
"type": "object",
|
|
329
|
+
"required": [
|
|
330
|
+
"walletAddressUrl",
|
|
331
|
+
"clientWalletAddress"
|
|
332
|
+
],
|
|
333
|
+
"properties": {
|
|
334
|
+
"walletAddressUrl": {
|
|
335
|
+
"type": "string",
|
|
336
|
+
"description": "Wallet address URL"
|
|
337
|
+
},
|
|
338
|
+
"clientWalletAddress": {
|
|
339
|
+
"type": "string",
|
|
340
|
+
"description": "Client's wallet address"
|
|
341
|
+
},
|
|
342
|
+
"incomingPaymentId": {
|
|
343
|
+
"type": "string",
|
|
344
|
+
"description": "ID of the incoming payment to retrieve"
|
|
345
|
+
},
|
|
346
|
+
"outgoingPaymentId": {
|
|
347
|
+
"type": "string",
|
|
348
|
+
"description": "ID of the outgoing payment to retrieve"
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
"steps": [
|
|
353
|
+
{
|
|
354
|
+
"stepId": "getWalletAddress",
|
|
355
|
+
"description": "Resolve the wallet address.\n",
|
|
356
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
357
|
+
"successCriteria": [
|
|
358
|
+
{
|
|
359
|
+
"condition": "$statusCode == 200"
|
|
360
|
+
}
|
|
361
|
+
],
|
|
362
|
+
"outputs": {
|
|
363
|
+
"authServer": "$response.body.authServer"
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"stepId": "requestReadGrant",
|
|
368
|
+
"description": "Request a non-interactive grant with `read` permissions for both incoming and outgoing payments.\n",
|
|
369
|
+
"operationId": "authServer.post-request",
|
|
370
|
+
"requestBody": {
|
|
371
|
+
"contentType": "application/json",
|
|
372
|
+
"payload": {
|
|
373
|
+
"access_token": {
|
|
374
|
+
"access": [
|
|
375
|
+
{
|
|
376
|
+
"type": "incoming-payment",
|
|
377
|
+
"actions": [
|
|
378
|
+
"read"
|
|
379
|
+
],
|
|
380
|
+
"identifier": "$inputs.walletAddressUrl"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"type": "outgoing-payment",
|
|
384
|
+
"actions": [
|
|
385
|
+
"read"
|
|
386
|
+
],
|
|
387
|
+
"identifier": "$inputs.walletAddressUrl"
|
|
388
|
+
}
|
|
389
|
+
]
|
|
390
|
+
},
|
|
391
|
+
"client": "$inputs.clientWalletAddress"
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
"successCriteria": [
|
|
395
|
+
{
|
|
396
|
+
"condition": "$statusCode == 200"
|
|
397
|
+
}
|
|
398
|
+
],
|
|
399
|
+
"outputs": {
|
|
400
|
+
"accessToken": "$response.body.access_token.value"
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"stepId": "getIncomingPayment",
|
|
405
|
+
"description": "Retrieve the details of a specific incoming payment. The response includes received amounts, completion status, and payment methods.\n",
|
|
406
|
+
"operationId": "resourceServer.get-incoming-payment",
|
|
407
|
+
"parameters": [
|
|
408
|
+
{
|
|
409
|
+
"name": "id",
|
|
410
|
+
"in": "path",
|
|
411
|
+
"value": "$inputs.incomingPaymentId"
|
|
412
|
+
}
|
|
413
|
+
],
|
|
414
|
+
"successCriteria": [
|
|
415
|
+
{
|
|
416
|
+
"condition": "$statusCode == 200"
|
|
417
|
+
}
|
|
418
|
+
],
|
|
419
|
+
"outputs": {
|
|
420
|
+
"incomingPayment": "$response.body"
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
"stepId": "getOutgoingPayment",
|
|
425
|
+
"description": "Retrieve the details of a specific outgoing payment. The response includes sent amounts, failure status, and payment metadata.\n",
|
|
426
|
+
"operationId": "resourceServer.get-outgoing-payment",
|
|
427
|
+
"parameters": [
|
|
428
|
+
{
|
|
429
|
+
"name": "id",
|
|
430
|
+
"in": "path",
|
|
431
|
+
"value": "$inputs.outgoingPaymentId"
|
|
432
|
+
}
|
|
433
|
+
],
|
|
434
|
+
"successCriteria": [
|
|
435
|
+
{
|
|
436
|
+
"condition": "$statusCode == 200"
|
|
437
|
+
}
|
|
438
|
+
],
|
|
439
|
+
"outputs": {
|
|
440
|
+
"outgoingPayment": "$response.body"
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
],
|
|
444
|
+
"outputs": {
|
|
445
|
+
"incomingPayment": "$steps.getIncomingPayment.outputs.incomingPayment",
|
|
446
|
+
"outgoingPayment": "$steps.getOutgoingPayment.outputs.outgoingPayment"
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
const result = await executeWorkflow(workflow, {
|
|
450
|
+
inputs: inputs,
|
|
451
|
+
serverUrls: this.serverUrls,
|
|
452
|
+
authProvider: this.authProvider,
|
|
453
|
+
hooks: this.hooks,
|
|
454
|
+
interactionHandler: this.interactionHandler,
|
|
455
|
+
});
|
|
456
|
+
if (!result.success) {
|
|
457
|
+
throw new Error(`Workflow "getPaymentDetails" failed: ${result.error || 'Unknown error'}`);
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
...result.outputs,
|
|
461
|
+
_raw: result,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Rotate an existing GNAP access token
|
|
466
|
+
*/
|
|
467
|
+
async rotateAccessToken(inputs) {
|
|
468
|
+
const workflow = {
|
|
469
|
+
"workflowId": "rotateAccessToken",
|
|
470
|
+
"summary": "Rotate an existing GNAP access token",
|
|
471
|
+
"description": "Rotate an access token by calling its management URI. The AS responds\nwith a new access token that has the same access rights as the original.\nThe original token is invalidated upon successful rotation.\n",
|
|
472
|
+
"inputs": {
|
|
473
|
+
"type": "object",
|
|
474
|
+
"required": [
|
|
475
|
+
"tokenManageUrl"
|
|
476
|
+
],
|
|
477
|
+
"properties": {
|
|
478
|
+
"tokenManageUrl": {
|
|
479
|
+
"type": "string",
|
|
480
|
+
"description": "The `manage` URL of the access token to rotate. This was provided in the original grant response as `access_token.manage`.\n"
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
"steps": [
|
|
485
|
+
{
|
|
486
|
+
"stepId": "rotateToken",
|
|
487
|
+
"description": "Call the token management endpoint to rotate the access token. The original token's value is sent in the Authorization header (handled by the HTTP signature layer). The AS returns a new access token with fresh `value`, `manage` URL, and `expires_in`.\n",
|
|
488
|
+
"operationId": "authServer.post-token",
|
|
489
|
+
"parameters": [
|
|
490
|
+
{
|
|
491
|
+
"name": "id",
|
|
492
|
+
"in": "path",
|
|
493
|
+
"value": "$inputs.tokenManageUrl"
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
"successCriteria": [
|
|
497
|
+
{
|
|
498
|
+
"condition": "$statusCode == 200"
|
|
499
|
+
}
|
|
500
|
+
],
|
|
501
|
+
"outputs": {
|
|
502
|
+
"newAccessTokenValue": "$response.body.access_token.value",
|
|
503
|
+
"newManageUrl": "$response.body.access_token.manage",
|
|
504
|
+
"expiresIn": "$response.body.access_token.expires_in",
|
|
505
|
+
"access": "$response.body.access_token.access"
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
],
|
|
509
|
+
"outputs": {
|
|
510
|
+
"accessToken": "$steps.rotateToken.outputs.newAccessTokenValue",
|
|
511
|
+
"manageUrl": "$steps.rotateToken.outputs.newManageUrl",
|
|
512
|
+
"expiresIn": "$steps.rotateToken.outputs.expiresIn"
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
const result = await executeWorkflow(workflow, {
|
|
516
|
+
inputs: inputs,
|
|
517
|
+
serverUrls: this.serverUrls,
|
|
518
|
+
authProvider: this.authProvider,
|
|
519
|
+
hooks: this.hooks,
|
|
520
|
+
interactionHandler: this.interactionHandler,
|
|
521
|
+
});
|
|
522
|
+
if (!result.success) {
|
|
523
|
+
throw new Error(`Workflow "rotateAccessToken" failed: ${result.error || 'Unknown error'}`);
|
|
524
|
+
}
|
|
525
|
+
return {
|
|
526
|
+
...result.outputs,
|
|
527
|
+
_raw: result,
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Revoke an active GNAP access token
|
|
532
|
+
*/
|
|
533
|
+
async revokeAccessToken(inputs) {
|
|
534
|
+
const workflow = {
|
|
535
|
+
"workflowId": "revokeAccessToken",
|
|
536
|
+
"summary": "Revoke an active GNAP access token",
|
|
537
|
+
"description": "Permanently revoke an access token by sending a DELETE request to its\nmanagement URI. After revocation, the token cannot be used to access\nany resources.\n",
|
|
538
|
+
"inputs": {
|
|
539
|
+
"type": "object",
|
|
540
|
+
"required": [
|
|
541
|
+
"tokenManageUrl"
|
|
542
|
+
],
|
|
543
|
+
"properties": {
|
|
544
|
+
"tokenManageUrl": {
|
|
545
|
+
"type": "string",
|
|
546
|
+
"description": "The `manage` URL of the access token to revoke.\n"
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
"steps": [
|
|
551
|
+
{
|
|
552
|
+
"stepId": "revokeToken",
|
|
553
|
+
"description": "Send a DELETE request to the token management endpoint to permanently revoke the access token.\n",
|
|
554
|
+
"operationId": "authServer.delete-token",
|
|
555
|
+
"parameters": [
|
|
556
|
+
{
|
|
557
|
+
"name": "id",
|
|
558
|
+
"in": "path",
|
|
559
|
+
"value": "$inputs.tokenManageUrl"
|
|
560
|
+
}
|
|
561
|
+
],
|
|
562
|
+
"successCriteria": [
|
|
563
|
+
{
|
|
564
|
+
"condition": "$statusCode == 204"
|
|
565
|
+
}
|
|
566
|
+
]
|
|
567
|
+
}
|
|
568
|
+
],
|
|
569
|
+
"outputs": {}
|
|
570
|
+
};
|
|
571
|
+
const result = await executeWorkflow(workflow, {
|
|
572
|
+
inputs: inputs,
|
|
573
|
+
serverUrls: this.serverUrls,
|
|
574
|
+
authProvider: this.authProvider,
|
|
575
|
+
hooks: this.hooks,
|
|
576
|
+
interactionHandler: this.interactionHandler,
|
|
577
|
+
});
|
|
578
|
+
if (!result.success) {
|
|
579
|
+
throw new Error(`Workflow "revokeAccessToken" failed: ${result.error || 'Unknown error'}`);
|
|
580
|
+
}
|
|
581
|
+
return {
|
|
582
|
+
...result.outputs,
|
|
583
|
+
_raw: result,
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Cancel an active GNAP grant
|
|
588
|
+
*/
|
|
589
|
+
async cancelGrant(inputs) {
|
|
590
|
+
const workflow = {
|
|
591
|
+
"workflowId": "cancelGrant",
|
|
592
|
+
"summary": "Cancel an active GNAP grant",
|
|
593
|
+
"description": "Cancel an active grant by sending a DELETE request to the continuation\nURI. This revokes all access tokens associated with the grant and\nprevents any further use of the grant's permissions.\n",
|
|
594
|
+
"inputs": {
|
|
595
|
+
"type": "object",
|
|
596
|
+
"required": [
|
|
597
|
+
"continueUri"
|
|
598
|
+
],
|
|
599
|
+
"properties": {
|
|
600
|
+
"continueUri": {
|
|
601
|
+
"type": "string",
|
|
602
|
+
"description": "The continuation URI from the original grant response (`continue.uri`).\n"
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
"steps": [
|
|
607
|
+
{
|
|
608
|
+
"stepId": "cancelGrant",
|
|
609
|
+
"description": "Send a DELETE request to the grant's continuation URI. The AS revokes all associated access tokens and cancels the grant.\n",
|
|
610
|
+
"operationId": "authServer.delete-continue",
|
|
611
|
+
"parameters": [
|
|
612
|
+
{
|
|
613
|
+
"name": "id",
|
|
614
|
+
"in": "path",
|
|
615
|
+
"value": "$inputs.continueUri"
|
|
616
|
+
}
|
|
617
|
+
],
|
|
618
|
+
"successCriteria": [
|
|
619
|
+
{
|
|
620
|
+
"condition": "$statusCode == 204"
|
|
621
|
+
}
|
|
622
|
+
]
|
|
623
|
+
}
|
|
624
|
+
],
|
|
625
|
+
"outputs": {}
|
|
626
|
+
};
|
|
627
|
+
const result = await executeWorkflow(workflow, {
|
|
628
|
+
inputs: inputs,
|
|
629
|
+
serverUrls: this.serverUrls,
|
|
630
|
+
authProvider: this.authProvider,
|
|
631
|
+
hooks: this.hooks,
|
|
632
|
+
interactionHandler: this.interactionHandler,
|
|
633
|
+
});
|
|
634
|
+
if (!result.success) {
|
|
635
|
+
throw new Error(`Workflow "cancelGrant" failed: ${result.error || 'Unknown error'}`);
|
|
636
|
+
}
|
|
637
|
+
return {
|
|
638
|
+
...result.outputs,
|
|
639
|
+
_raw: result,
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Set up a recurring payment grant with interval limits
|
|
644
|
+
*/
|
|
645
|
+
async setupRecurringPayment(inputs) {
|
|
646
|
+
const workflow = {
|
|
647
|
+
"workflowId": "setupRecurringPayment",
|
|
648
|
+
"summary": "Set up a recurring payment grant with interval limits",
|
|
649
|
+
"description": "Establishes a recurring payment authorization with the sender's ASE.\nAfter this workflow completes, the client holds an access token that\npermits creating outgoing payments within the specified interval and\namount limits without further user interaction.\n",
|
|
650
|
+
"inputs": {
|
|
651
|
+
"type": "object",
|
|
652
|
+
"required": [
|
|
653
|
+
"recipientWalletAddressUrl",
|
|
654
|
+
"senderWalletAddressUrl",
|
|
655
|
+
"debitAmountPerInterval",
|
|
656
|
+
"debitAssetCode",
|
|
657
|
+
"debitAssetScale",
|
|
658
|
+
"interval",
|
|
659
|
+
"clientWalletAddress"
|
|
660
|
+
],
|
|
661
|
+
"properties": {
|
|
662
|
+
"recipientWalletAddressUrl": {
|
|
663
|
+
"type": "string",
|
|
664
|
+
"description": "Recipient's wallet address URL"
|
|
665
|
+
},
|
|
666
|
+
"senderWalletAddressUrl": {
|
|
667
|
+
"type": "string",
|
|
668
|
+
"description": "Sender's wallet address URL"
|
|
669
|
+
},
|
|
670
|
+
"debitAmountPerInterval": {
|
|
671
|
+
"type": "string",
|
|
672
|
+
"description": "Maximum debit amount per interval (minor units)"
|
|
673
|
+
},
|
|
674
|
+
"debitAssetCode": {
|
|
675
|
+
"type": "string",
|
|
676
|
+
"description": "Currency code (e.g. USD)"
|
|
677
|
+
},
|
|
678
|
+
"debitAssetScale": {
|
|
679
|
+
"type": "integer",
|
|
680
|
+
"description": "Asset scale (e.g. 2)"
|
|
681
|
+
},
|
|
682
|
+
"interval": {
|
|
683
|
+
"type": "string",
|
|
684
|
+
"description": "ISO 8601 repeating interval (e.g. 'R12/2024-01-01T00:00:00Z/P1M' for 12 monthly periods starting Jan 1 2024)\n"
|
|
685
|
+
},
|
|
686
|
+
"clientWalletAddress": {
|
|
687
|
+
"type": "string",
|
|
688
|
+
"description": "Client's wallet address"
|
|
689
|
+
},
|
|
690
|
+
"finishUri": {
|
|
691
|
+
"type": "string",
|
|
692
|
+
"description": "Redirect URI after interaction"
|
|
693
|
+
},
|
|
694
|
+
"finishNonce": {
|
|
695
|
+
"type": "string",
|
|
696
|
+
"description": "Unique nonce for the finish step"
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
"steps": [
|
|
701
|
+
{
|
|
702
|
+
"stepId": "getRecipientWalletAddress",
|
|
703
|
+
"description": "Resolve the recipient's wallet address to discover auth and resource server URLs.\n",
|
|
704
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
705
|
+
"successCriteria": [
|
|
706
|
+
{
|
|
707
|
+
"condition": "$statusCode == 200"
|
|
708
|
+
}
|
|
709
|
+
],
|
|
710
|
+
"outputs": {
|
|
711
|
+
"recipientAuthServer": "$response.body.authServer",
|
|
712
|
+
"recipientResourceServer": "$response.body.resourceServer"
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"stepId": "requestIncomingPaymentGrant",
|
|
717
|
+
"description": "Request a non-interactive grant to create incoming payments on the recipient's ASE.\n",
|
|
718
|
+
"operationId": "authServer.post-request",
|
|
719
|
+
"requestBody": {
|
|
720
|
+
"contentType": "application/json",
|
|
721
|
+
"payload": {
|
|
722
|
+
"access_token": {
|
|
723
|
+
"access": [
|
|
724
|
+
{
|
|
725
|
+
"type": "incoming-payment",
|
|
726
|
+
"actions": [
|
|
727
|
+
"create",
|
|
728
|
+
"read"
|
|
729
|
+
],
|
|
730
|
+
"identifier": "$inputs.recipientWalletAddressUrl"
|
|
731
|
+
}
|
|
732
|
+
]
|
|
733
|
+
},
|
|
734
|
+
"client": "$inputs.clientWalletAddress"
|
|
735
|
+
}
|
|
736
|
+
},
|
|
737
|
+
"successCriteria": [
|
|
738
|
+
{
|
|
739
|
+
"condition": "$statusCode == 200"
|
|
740
|
+
}
|
|
741
|
+
],
|
|
742
|
+
"outputs": {
|
|
743
|
+
"incomingPaymentAccessToken": "$response.body.access_token.value"
|
|
744
|
+
}
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
"stepId": "createIncomingPayment",
|
|
748
|
+
"description": "Create an incoming payment without an `incomingAmount` since the exact receive amount will depend on exchange rates at payment time.\n",
|
|
749
|
+
"operationId": "resourceServer.create-incoming-payment",
|
|
750
|
+
"requestBody": {
|
|
751
|
+
"contentType": "application/json",
|
|
752
|
+
"payload": {
|
|
753
|
+
"walletAddress": "$inputs.recipientWalletAddressUrl"
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
"successCriteria": [
|
|
757
|
+
{
|
|
758
|
+
"condition": "$statusCode == 201"
|
|
759
|
+
}
|
|
760
|
+
],
|
|
761
|
+
"outputs": {
|
|
762
|
+
"incomingPaymentUrl": "$response.body.id"
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
"stepId": "getSenderWalletAddress",
|
|
767
|
+
"description": "Resolve the sender's wallet address for auth and resource server URLs.\n",
|
|
768
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
769
|
+
"successCriteria": [
|
|
770
|
+
{
|
|
771
|
+
"condition": "$statusCode == 200"
|
|
772
|
+
}
|
|
773
|
+
],
|
|
774
|
+
"outputs": {
|
|
775
|
+
"senderAuthServer": "$response.body.authServer",
|
|
776
|
+
"senderResourceServer": "$response.body.resourceServer"
|
|
777
|
+
}
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
"stepId": "requestQuoteGrant",
|
|
781
|
+
"description": "Request a non-interactive grant to create quotes on the sender's ASE.\n",
|
|
782
|
+
"operationId": "authServer.post-request",
|
|
783
|
+
"requestBody": {
|
|
784
|
+
"contentType": "application/json",
|
|
785
|
+
"payload": {
|
|
786
|
+
"access_token": {
|
|
787
|
+
"access": [
|
|
788
|
+
{
|
|
789
|
+
"type": "quote",
|
|
790
|
+
"actions": [
|
|
791
|
+
"create",
|
|
792
|
+
"read"
|
|
793
|
+
]
|
|
794
|
+
}
|
|
795
|
+
]
|
|
796
|
+
},
|
|
797
|
+
"client": "$inputs.clientWalletAddress"
|
|
798
|
+
}
|
|
799
|
+
},
|
|
800
|
+
"successCriteria": [
|
|
801
|
+
{
|
|
802
|
+
"condition": "$statusCode == 200"
|
|
803
|
+
}
|
|
804
|
+
],
|
|
805
|
+
"outputs": {
|
|
806
|
+
"quoteAccessToken": "$response.body.access_token.value"
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
"stepId": "createQuote",
|
|
811
|
+
"description": "Create a quote for the first interval's payment. This establishes the exchange rate and fees for the initial payment.\n",
|
|
812
|
+
"operationId": "resourceServer.create-quote",
|
|
813
|
+
"requestBody": {
|
|
814
|
+
"contentType": "application/json",
|
|
815
|
+
"payload": {
|
|
816
|
+
"walletAddress": "$inputs.senderWalletAddressUrl",
|
|
817
|
+
"receiver": "$steps.createIncomingPayment.outputs.incomingPaymentUrl",
|
|
818
|
+
"method": "ilp",
|
|
819
|
+
"debitAmount": {
|
|
820
|
+
"value": "$inputs.debitAmountPerInterval",
|
|
821
|
+
"assetCode": "$inputs.debitAssetCode",
|
|
822
|
+
"assetScale": "$inputs.debitAssetScale"
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
},
|
|
826
|
+
"successCriteria": [
|
|
827
|
+
{
|
|
828
|
+
"condition": "$statusCode == 201"
|
|
829
|
+
}
|
|
830
|
+
],
|
|
831
|
+
"outputs": {
|
|
832
|
+
"quoteId": "$response.body.id",
|
|
833
|
+
"debitAmount": "$response.body.debitAmount",
|
|
834
|
+
"receiveAmount": "$response.body.receiveAmount"
|
|
835
|
+
}
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
"stepId": "requestRecurringGrant",
|
|
839
|
+
"description": "Request an interactive grant for the outgoing payment with `limits.interval` set. The interval defines how often the client can create outgoing payments and the maximum amount per interval. The user must consent to this recurring authorization.\n",
|
|
840
|
+
"operationId": "authServer.post-request",
|
|
841
|
+
"requestBody": {
|
|
842
|
+
"contentType": "application/json",
|
|
843
|
+
"payload": {
|
|
844
|
+
"access_token": {
|
|
845
|
+
"access": [
|
|
846
|
+
{
|
|
847
|
+
"type": "outgoing-payment",
|
|
848
|
+
"actions": [
|
|
849
|
+
"create",
|
|
850
|
+
"read"
|
|
851
|
+
],
|
|
852
|
+
"identifier": "$inputs.senderWalletAddressUrl",
|
|
853
|
+
"limits": {
|
|
854
|
+
"receiver": "$steps.createIncomingPayment.outputs.incomingPaymentUrl",
|
|
855
|
+
"interval": "$inputs.interval",
|
|
856
|
+
"debitAmount": {
|
|
857
|
+
"value": "$inputs.debitAmountPerInterval",
|
|
858
|
+
"assetCode": "$inputs.debitAssetCode",
|
|
859
|
+
"assetScale": "$inputs.debitAssetScale"
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
]
|
|
864
|
+
},
|
|
865
|
+
"client": "$inputs.clientWalletAddress",
|
|
866
|
+
"interact": {
|
|
867
|
+
"start": [
|
|
868
|
+
"redirect"
|
|
869
|
+
],
|
|
870
|
+
"finish": {
|
|
871
|
+
"method": "redirect",
|
|
872
|
+
"uri": "$inputs.finishUri",
|
|
873
|
+
"nonce": "$inputs.finishNonce"
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
},
|
|
878
|
+
"successCriteria": [
|
|
879
|
+
{
|
|
880
|
+
"condition": "$statusCode == 200"
|
|
881
|
+
}
|
|
882
|
+
],
|
|
883
|
+
"outputs": {
|
|
884
|
+
"interactRedirectUri": "$response.body.interact.redirect",
|
|
885
|
+
"continueAccessToken": "$response.body.continue.access_token.value",
|
|
886
|
+
"continueUri": "$response.body.continue.uri"
|
|
887
|
+
}
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
"stepId": "continueRecurringGrant",
|
|
891
|
+
"description": "Continue the grant after the user has consented to the recurring payment. The resulting access token permits creating outgoing payments within the interval and amount limits.\n",
|
|
892
|
+
"operationId": "authServer.post-continue",
|
|
893
|
+
"parameters": [
|
|
894
|
+
{
|
|
895
|
+
"name": "id",
|
|
896
|
+
"in": "path",
|
|
897
|
+
"value": "$steps.requestRecurringGrant.outputs.continueUri"
|
|
898
|
+
}
|
|
899
|
+
],
|
|
900
|
+
"requestBody": {
|
|
901
|
+
"contentType": "application/json",
|
|
902
|
+
"payload": {
|
|
903
|
+
"interact_ref": "{interact_ref_from_redirect}"
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
"successCriteria": [
|
|
907
|
+
{
|
|
908
|
+
"condition": "$statusCode == 200"
|
|
909
|
+
}
|
|
910
|
+
],
|
|
911
|
+
"outputs": {
|
|
912
|
+
"outgoingPaymentAccessToken": "$response.body.access_token.value",
|
|
913
|
+
"outgoingPaymentManageUrl": "$response.body.access_token.manage"
|
|
914
|
+
}
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
"stepId": "createOutgoingPayment",
|
|
918
|
+
"description": "Create the first outgoing payment using the recurring grant. Subsequent payments within the allowed interval can be created by repeating the quote + outgoing payment steps without additional user interaction.\n",
|
|
919
|
+
"operationId": "resourceServer.create-outgoing-payment",
|
|
920
|
+
"requestBody": {
|
|
921
|
+
"contentType": "application/json",
|
|
922
|
+
"payload": {
|
|
923
|
+
"walletAddress": "$inputs.senderWalletAddressUrl",
|
|
924
|
+
"quoteId": "$steps.createQuote.outputs.quoteId"
|
|
925
|
+
}
|
|
926
|
+
},
|
|
927
|
+
"successCriteria": [
|
|
928
|
+
{
|
|
929
|
+
"condition": "$statusCode == 201"
|
|
930
|
+
}
|
|
931
|
+
],
|
|
932
|
+
"outputs": {
|
|
933
|
+
"outgoingPaymentId": "$response.body.id",
|
|
934
|
+
"outgoingPaymentFailed": "$response.body.failed"
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
],
|
|
938
|
+
"outputs": {
|
|
939
|
+
"outgoingPaymentAccessToken": "$steps.continueRecurringGrant.outputs.outgoingPaymentAccessToken",
|
|
940
|
+
"outgoingPaymentManageUrl": "$steps.continueRecurringGrant.outputs.outgoingPaymentManageUrl",
|
|
941
|
+
"firstPaymentId": "$steps.createOutgoingPayment.outputs.outgoingPaymentId",
|
|
942
|
+
"incomingPaymentUrl": "$steps.createIncomingPayment.outputs.incomingPaymentUrl"
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
const result = await executeWorkflow(workflow, {
|
|
946
|
+
inputs: inputs,
|
|
947
|
+
serverUrls: this.serverUrls,
|
|
948
|
+
authProvider: this.authProvider,
|
|
949
|
+
hooks: this.hooks,
|
|
950
|
+
interactionHandler: this.interactionHandler,
|
|
951
|
+
});
|
|
952
|
+
if (!result.success) {
|
|
953
|
+
throw new Error(`Workflow "setupRecurringPayment" failed: ${result.error || 'Unknown error'}`);
|
|
954
|
+
}
|
|
955
|
+
return {
|
|
956
|
+
...result.outputs,
|
|
957
|
+
_raw: result,
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* One-time payment with a fixed send (debit) amount
|
|
962
|
+
*/
|
|
963
|
+
async oneTimePaymentFixedSend(inputs) {
|
|
964
|
+
const workflow = {
|
|
965
|
+
"workflowId": "oneTimePaymentFixedSend",
|
|
966
|
+
"summary": "One-time payment with a fixed send (debit) amount",
|
|
967
|
+
"description": "Complete Open Payments flow where the sender specifies how much to\ndebit from their account. The incoming payment has no `incomingAmount`,\nand the quote uses `debitAmount` to fix the sender's side.\n",
|
|
968
|
+
"inputs": {
|
|
969
|
+
"type": "object",
|
|
970
|
+
"required": [
|
|
971
|
+
"recipientWalletAddressUrl",
|
|
972
|
+
"senderWalletAddressUrl",
|
|
973
|
+
"debitAmount",
|
|
974
|
+
"debitAssetCode",
|
|
975
|
+
"debitAssetScale",
|
|
976
|
+
"clientWalletAddress"
|
|
977
|
+
],
|
|
978
|
+
"properties": {
|
|
979
|
+
"recipientWalletAddressUrl": {
|
|
980
|
+
"type": "string",
|
|
981
|
+
"description": "The recipient's wallet address URL"
|
|
982
|
+
},
|
|
983
|
+
"senderWalletAddressUrl": {
|
|
984
|
+
"type": "string",
|
|
985
|
+
"description": "The sender's wallet address URL"
|
|
986
|
+
},
|
|
987
|
+
"debitAmount": {
|
|
988
|
+
"type": "string",
|
|
989
|
+
"description": "Amount to debit in minor units (e.g. '2500' for $25.00 with scale 2)"
|
|
990
|
+
},
|
|
991
|
+
"debitAssetCode": {
|
|
992
|
+
"type": "string",
|
|
993
|
+
"description": "Currency code of the sender's asset (e.g. USD)"
|
|
994
|
+
},
|
|
995
|
+
"debitAssetScale": {
|
|
996
|
+
"type": "integer",
|
|
997
|
+
"description": "Asset scale (e.g. 2 for USD cents)"
|
|
998
|
+
},
|
|
999
|
+
"clientWalletAddress": {
|
|
1000
|
+
"type": "string",
|
|
1001
|
+
"description": "The client's wallet address for GNAP identification"
|
|
1002
|
+
},
|
|
1003
|
+
"finishUri": {
|
|
1004
|
+
"type": "string",
|
|
1005
|
+
"description": "URI to redirect the user to after interaction"
|
|
1006
|
+
},
|
|
1007
|
+
"finishNonce": {
|
|
1008
|
+
"type": "string",
|
|
1009
|
+
"description": "Unique nonce for the interaction finish"
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
"steps": [
|
|
1014
|
+
{
|
|
1015
|
+
"stepId": "getRecipientWalletAddress",
|
|
1016
|
+
"description": "Retrieve the recipient's wallet address details to discover server URLs and supported asset information.\n",
|
|
1017
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
1018
|
+
"successCriteria": [
|
|
1019
|
+
{
|
|
1020
|
+
"condition": "$statusCode == 200"
|
|
1021
|
+
}
|
|
1022
|
+
],
|
|
1023
|
+
"outputs": {
|
|
1024
|
+
"recipientAuthServer": "$response.body.authServer",
|
|
1025
|
+
"recipientResourceServer": "$response.body.resourceServer"
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1028
|
+
{
|
|
1029
|
+
"stepId": "requestIncomingPaymentGrant",
|
|
1030
|
+
"description": "Request a non-interactive grant from the recipient's authorization server to create and read incoming payments.\n",
|
|
1031
|
+
"operationId": "authServer.post-request",
|
|
1032
|
+
"requestBody": {
|
|
1033
|
+
"contentType": "application/json",
|
|
1034
|
+
"payload": {
|
|
1035
|
+
"access_token": {
|
|
1036
|
+
"access": [
|
|
1037
|
+
{
|
|
1038
|
+
"type": "incoming-payment",
|
|
1039
|
+
"actions": [
|
|
1040
|
+
"create",
|
|
1041
|
+
"read"
|
|
1042
|
+
],
|
|
1043
|
+
"identifier": "$inputs.recipientWalletAddressUrl"
|
|
1044
|
+
}
|
|
1045
|
+
]
|
|
1046
|
+
},
|
|
1047
|
+
"client": "$inputs.clientWalletAddress"
|
|
1048
|
+
}
|
|
1049
|
+
},
|
|
1050
|
+
"successCriteria": [
|
|
1051
|
+
{
|
|
1052
|
+
"condition": "$statusCode == 200"
|
|
1053
|
+
}
|
|
1054
|
+
],
|
|
1055
|
+
"outputs": {
|
|
1056
|
+
"incomingPaymentAccessToken": "$response.body.access_token.value"
|
|
1057
|
+
}
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
"stepId": "createIncomingPayment",
|
|
1061
|
+
"description": "Create an incoming payment on the recipient's account WITHOUT specifying an `incomingAmount`. This creates an open-ended incoming payment where the received amount will be determined by the quote and exchange rate.\n",
|
|
1062
|
+
"operationId": "resourceServer.create-incoming-payment",
|
|
1063
|
+
"requestBody": {
|
|
1064
|
+
"contentType": "application/json",
|
|
1065
|
+
"payload": {
|
|
1066
|
+
"walletAddress": "$inputs.recipientWalletAddressUrl"
|
|
1067
|
+
}
|
|
1068
|
+
},
|
|
1069
|
+
"successCriteria": [
|
|
1070
|
+
{
|
|
1071
|
+
"condition": "$statusCode == 201"
|
|
1072
|
+
}
|
|
1073
|
+
],
|
|
1074
|
+
"outputs": {
|
|
1075
|
+
"incomingPaymentUrl": "$response.body.id"
|
|
1076
|
+
}
|
|
1077
|
+
},
|
|
1078
|
+
{
|
|
1079
|
+
"stepId": "getSenderWalletAddress",
|
|
1080
|
+
"description": "Retrieve the sender's wallet address details to discover the sender's authorization and resource server URLs.\n",
|
|
1081
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
1082
|
+
"successCriteria": [
|
|
1083
|
+
{
|
|
1084
|
+
"condition": "$statusCode == 200"
|
|
1085
|
+
}
|
|
1086
|
+
],
|
|
1087
|
+
"outputs": {
|
|
1088
|
+
"senderAuthServer": "$response.body.authServer",
|
|
1089
|
+
"senderResourceServer": "$response.body.resourceServer"
|
|
1090
|
+
}
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
"stepId": "requestQuoteGrant",
|
|
1094
|
+
"description": "Request a non-interactive grant from the sender's authorization server to create and read quotes.\n",
|
|
1095
|
+
"operationId": "authServer.post-request",
|
|
1096
|
+
"requestBody": {
|
|
1097
|
+
"contentType": "application/json",
|
|
1098
|
+
"payload": {
|
|
1099
|
+
"access_token": {
|
|
1100
|
+
"access": [
|
|
1101
|
+
{
|
|
1102
|
+
"type": "quote",
|
|
1103
|
+
"actions": [
|
|
1104
|
+
"create",
|
|
1105
|
+
"read"
|
|
1106
|
+
]
|
|
1107
|
+
}
|
|
1108
|
+
]
|
|
1109
|
+
},
|
|
1110
|
+
"client": "$inputs.clientWalletAddress"
|
|
1111
|
+
}
|
|
1112
|
+
},
|
|
1113
|
+
"successCriteria": [
|
|
1114
|
+
{
|
|
1115
|
+
"condition": "$statusCode == 200"
|
|
1116
|
+
}
|
|
1117
|
+
],
|
|
1118
|
+
"outputs": {
|
|
1119
|
+
"quoteAccessToken": "$response.body.access_token.value"
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
"stepId": "createQuote",
|
|
1124
|
+
"description": "Create a quote on the sender's account with a fixed `debitAmount`. The sender's ASE calculates the corresponding receive amount based on the exchange rate, fees, and the quote method.\n",
|
|
1125
|
+
"operationId": "resourceServer.create-quote",
|
|
1126
|
+
"requestBody": {
|
|
1127
|
+
"contentType": "application/json",
|
|
1128
|
+
"payload": {
|
|
1129
|
+
"walletAddress": "$inputs.senderWalletAddressUrl",
|
|
1130
|
+
"receiver": "$steps.createIncomingPayment.outputs.incomingPaymentUrl",
|
|
1131
|
+
"method": "ilp",
|
|
1132
|
+
"debitAmount": {
|
|
1133
|
+
"value": "$inputs.debitAmount",
|
|
1134
|
+
"assetCode": "$inputs.debitAssetCode",
|
|
1135
|
+
"assetScale": "$inputs.debitAssetScale"
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
},
|
|
1139
|
+
"successCriteria": [
|
|
1140
|
+
{
|
|
1141
|
+
"condition": "$statusCode == 201"
|
|
1142
|
+
}
|
|
1143
|
+
],
|
|
1144
|
+
"outputs": {
|
|
1145
|
+
"quoteId": "$response.body.id",
|
|
1146
|
+
"debitAmount": "$response.body.debitAmount",
|
|
1147
|
+
"receiveAmount": "$response.body.receiveAmount"
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
"stepId": "requestOutgoingPaymentGrant",
|
|
1152
|
+
"description": "Request an interactive grant from the sender's authorization server for the outgoing payment. The user must explicitly consent to the payment through the redirect flow.\n",
|
|
1153
|
+
"operationId": "authServer.post-request",
|
|
1154
|
+
"requestBody": {
|
|
1155
|
+
"contentType": "application/json",
|
|
1156
|
+
"payload": {
|
|
1157
|
+
"access_token": {
|
|
1158
|
+
"access": [
|
|
1159
|
+
{
|
|
1160
|
+
"type": "outgoing-payment",
|
|
1161
|
+
"actions": [
|
|
1162
|
+
"create",
|
|
1163
|
+
"read"
|
|
1164
|
+
],
|
|
1165
|
+
"identifier": "$inputs.senderWalletAddressUrl",
|
|
1166
|
+
"limits": {
|
|
1167
|
+
"debitAmount": "$steps.createQuote.outputs.debitAmount",
|
|
1168
|
+
"receiveAmount": "$steps.createQuote.outputs.receiveAmount",
|
|
1169
|
+
"receiver": "$steps.createIncomingPayment.outputs.incomingPaymentUrl"
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
]
|
|
1173
|
+
},
|
|
1174
|
+
"client": "$inputs.clientWalletAddress",
|
|
1175
|
+
"interact": {
|
|
1176
|
+
"start": [
|
|
1177
|
+
"redirect"
|
|
1178
|
+
],
|
|
1179
|
+
"finish": {
|
|
1180
|
+
"method": "redirect",
|
|
1181
|
+
"uri": "$inputs.finishUri",
|
|
1182
|
+
"nonce": "$inputs.finishNonce"
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
},
|
|
1187
|
+
"successCriteria": [
|
|
1188
|
+
{
|
|
1189
|
+
"condition": "$statusCode == 200"
|
|
1190
|
+
}
|
|
1191
|
+
],
|
|
1192
|
+
"outputs": {
|
|
1193
|
+
"interactRedirectUri": "$response.body.interact.redirect",
|
|
1194
|
+
"continueAccessToken": "$response.body.continue.access_token.value",
|
|
1195
|
+
"continueUri": "$response.body.continue.uri"
|
|
1196
|
+
}
|
|
1197
|
+
},
|
|
1198
|
+
{
|
|
1199
|
+
"stepId": "continueOutgoingPaymentGrant",
|
|
1200
|
+
"description": "After the sender completes the interaction (consents to the payment), the client continues the grant to obtain the access token.\n",
|
|
1201
|
+
"operationId": "authServer.post-continue",
|
|
1202
|
+
"parameters": [
|
|
1203
|
+
{
|
|
1204
|
+
"name": "id",
|
|
1205
|
+
"in": "path",
|
|
1206
|
+
"value": "$steps.requestOutgoingPaymentGrant.outputs.continueUri"
|
|
1207
|
+
}
|
|
1208
|
+
],
|
|
1209
|
+
"requestBody": {
|
|
1210
|
+
"contentType": "application/json",
|
|
1211
|
+
"payload": {
|
|
1212
|
+
"interact_ref": "{interact_ref_from_redirect}"
|
|
1213
|
+
}
|
|
1214
|
+
},
|
|
1215
|
+
"successCriteria": [
|
|
1216
|
+
{
|
|
1217
|
+
"condition": "$statusCode == 200"
|
|
1218
|
+
}
|
|
1219
|
+
],
|
|
1220
|
+
"outputs": {
|
|
1221
|
+
"outgoingPaymentAccessToken": "$response.body.access_token.value"
|
|
1222
|
+
}
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
"stepId": "createOutgoingPayment",
|
|
1226
|
+
"description": "Create the outgoing payment using the quote. This triggers the actual payment execution between the two ASEs.\n",
|
|
1227
|
+
"operationId": "resourceServer.create-outgoing-payment",
|
|
1228
|
+
"requestBody": {
|
|
1229
|
+
"contentType": "application/json",
|
|
1230
|
+
"payload": {
|
|
1231
|
+
"walletAddress": "$inputs.senderWalletAddressUrl",
|
|
1232
|
+
"quoteId": "$steps.createQuote.outputs.quoteId"
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
"successCriteria": [
|
|
1236
|
+
{
|
|
1237
|
+
"condition": "$statusCode == 201"
|
|
1238
|
+
}
|
|
1239
|
+
],
|
|
1240
|
+
"outputs": {
|
|
1241
|
+
"outgoingPaymentId": "$response.body.id",
|
|
1242
|
+
"outgoingPaymentFailed": "$response.body.failed",
|
|
1243
|
+
"sentAmount": "$response.body.sentAmount"
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
],
|
|
1247
|
+
"outputs": {
|
|
1248
|
+
"incomingPaymentUrl": "$steps.createIncomingPayment.outputs.incomingPaymentUrl",
|
|
1249
|
+
"quoteId": "$steps.createQuote.outputs.quoteId",
|
|
1250
|
+
"outgoingPaymentId": "$steps.createOutgoingPayment.outputs.outgoingPaymentId",
|
|
1251
|
+
"debitAmount": "$steps.createQuote.outputs.debitAmount",
|
|
1252
|
+
"receiveAmount": "$steps.createQuote.outputs.receiveAmount"
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
const result = await executeWorkflow(workflow, {
|
|
1256
|
+
inputs: inputs,
|
|
1257
|
+
serverUrls: this.serverUrls,
|
|
1258
|
+
authProvider: this.authProvider,
|
|
1259
|
+
hooks: this.hooks,
|
|
1260
|
+
interactionHandler: this.interactionHandler,
|
|
1261
|
+
});
|
|
1262
|
+
if (!result.success) {
|
|
1263
|
+
throw new Error(`Workflow "oneTimePaymentFixedSend" failed: ${result.error || 'Unknown error'}`);
|
|
1264
|
+
}
|
|
1265
|
+
return {
|
|
1266
|
+
...result.outputs,
|
|
1267
|
+
_raw: result,
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* One-time payment with a fixed receive amount
|
|
1272
|
+
*/
|
|
1273
|
+
async oneTimePaymentFixedReceive(inputs) {
|
|
1274
|
+
const workflow = {
|
|
1275
|
+
"workflowId": "oneTimePaymentFixedReceive",
|
|
1276
|
+
"summary": "One-time payment with a fixed receive amount",
|
|
1277
|
+
"description": "Complete Open Payments flow for a one-time payment where the incoming\npayment has an `incomingAmount` set. This is the standard e-commerce\ncheckout pattern where the merchant knows exactly how much should be\nreceived.\n",
|
|
1278
|
+
"inputs": {
|
|
1279
|
+
"type": "object",
|
|
1280
|
+
"required": [
|
|
1281
|
+
"recipientWalletAddressUrl",
|
|
1282
|
+
"senderWalletAddressUrl",
|
|
1283
|
+
"amount",
|
|
1284
|
+
"assetCode",
|
|
1285
|
+
"assetScale",
|
|
1286
|
+
"clientWalletAddress"
|
|
1287
|
+
],
|
|
1288
|
+
"properties": {
|
|
1289
|
+
"recipientWalletAddressUrl": {
|
|
1290
|
+
"type": "string",
|
|
1291
|
+
"description": "The recipient's wallet address URL (e.g. https://wallet.example.com/alice)"
|
|
1292
|
+
},
|
|
1293
|
+
"senderWalletAddressUrl": {
|
|
1294
|
+
"type": "string",
|
|
1295
|
+
"description": "The sender's wallet address URL (e.g. https://wallet.example.com/bob)"
|
|
1296
|
+
},
|
|
1297
|
+
"amount": {
|
|
1298
|
+
"type": "string",
|
|
1299
|
+
"description": "Amount to receive in minor units (e.g. '2500' for $25.00 with scale 2)"
|
|
1300
|
+
},
|
|
1301
|
+
"assetCode": {
|
|
1302
|
+
"type": "string",
|
|
1303
|
+
"description": "Currency code (e.g. USD)"
|
|
1304
|
+
},
|
|
1305
|
+
"assetScale": {
|
|
1306
|
+
"type": "integer",
|
|
1307
|
+
"description": "Asset scale (e.g. 2 for USD cents)"
|
|
1308
|
+
},
|
|
1309
|
+
"clientWalletAddress": {
|
|
1310
|
+
"type": "string",
|
|
1311
|
+
"description": "The client's wallet address for GNAP identification"
|
|
1312
|
+
},
|
|
1313
|
+
"finishUri": {
|
|
1314
|
+
"type": "string",
|
|
1315
|
+
"description": "URI to redirect the user to after interaction (optional, defaults to client callback)"
|
|
1316
|
+
},
|
|
1317
|
+
"finishNonce": {
|
|
1318
|
+
"type": "string",
|
|
1319
|
+
"description": "Unique nonce for the interaction finish (optional)"
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
},
|
|
1323
|
+
"steps": [
|
|
1324
|
+
{
|
|
1325
|
+
"stepId": "getRecipientWalletAddress",
|
|
1326
|
+
"description": "Retrieve the recipient's wallet address details to discover the authorization server URL and resource server URL.\n",
|
|
1327
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
1328
|
+
"successCriteria": [
|
|
1329
|
+
{
|
|
1330
|
+
"condition": "$statusCode == 200"
|
|
1331
|
+
}
|
|
1332
|
+
],
|
|
1333
|
+
"outputs": {
|
|
1334
|
+
"recipientAuthServer": "$response.body.authServer",
|
|
1335
|
+
"recipientResourceServer": "$response.body.resourceServer",
|
|
1336
|
+
"recipientAssetCode": "$response.body.assetCode",
|
|
1337
|
+
"recipientAssetScale": "$response.body.assetScale"
|
|
1338
|
+
}
|
|
1339
|
+
},
|
|
1340
|
+
{
|
|
1341
|
+
"stepId": "requestIncomingPaymentGrant",
|
|
1342
|
+
"description": "Request a non-interactive grant from the recipient's authorization server to create an incoming payment resource.\n",
|
|
1343
|
+
"operationId": "authServer.post-request",
|
|
1344
|
+
"requestBody": {
|
|
1345
|
+
"contentType": "application/json",
|
|
1346
|
+
"payload": {
|
|
1347
|
+
"access_token": {
|
|
1348
|
+
"access": [
|
|
1349
|
+
{
|
|
1350
|
+
"type": "incoming-payment",
|
|
1351
|
+
"actions": [
|
|
1352
|
+
"create",
|
|
1353
|
+
"read"
|
|
1354
|
+
],
|
|
1355
|
+
"identifier": "$inputs.recipientWalletAddressUrl"
|
|
1356
|
+
}
|
|
1357
|
+
]
|
|
1358
|
+
},
|
|
1359
|
+
"client": "$inputs.clientWalletAddress"
|
|
1360
|
+
}
|
|
1361
|
+
},
|
|
1362
|
+
"successCriteria": [
|
|
1363
|
+
{
|
|
1364
|
+
"condition": "$statusCode == 200"
|
|
1365
|
+
}
|
|
1366
|
+
],
|
|
1367
|
+
"outputs": {
|
|
1368
|
+
"incomingPaymentAccessToken": "$response.body.access_token.value",
|
|
1369
|
+
"incomingPaymentContinueUri": "$response.body.continue.uri"
|
|
1370
|
+
}
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
"stepId": "createIncomingPayment",
|
|
1374
|
+
"description": "Create an incoming payment resource on the recipient's account with the fixed receive amount. The response includes unique payment details (e.g. ILP address) for addressing payments to the recipient.\n",
|
|
1375
|
+
"operationId": "resourceServer.create-incoming-payment",
|
|
1376
|
+
"requestBody": {
|
|
1377
|
+
"contentType": "application/json",
|
|
1378
|
+
"payload": {
|
|
1379
|
+
"walletAddress": "$inputs.recipientWalletAddressUrl",
|
|
1380
|
+
"incomingAmount": {
|
|
1381
|
+
"value": "$inputs.amount",
|
|
1382
|
+
"assetCode": "$inputs.assetCode",
|
|
1383
|
+
"assetScale": "$inputs.assetScale"
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
},
|
|
1387
|
+
"successCriteria": [
|
|
1388
|
+
{
|
|
1389
|
+
"condition": "$statusCode == 201"
|
|
1390
|
+
}
|
|
1391
|
+
],
|
|
1392
|
+
"outputs": {
|
|
1393
|
+
"incomingPaymentUrl": "$response.body.id"
|
|
1394
|
+
}
|
|
1395
|
+
},
|
|
1396
|
+
{
|
|
1397
|
+
"stepId": "getSenderWalletAddress",
|
|
1398
|
+
"description": "Retrieve the sender's wallet address details to discover the sender's authorization and resource server URLs.\n",
|
|
1399
|
+
"operationId": "walletAddressServer.get-wallet-address",
|
|
1400
|
+
"successCriteria": [
|
|
1401
|
+
{
|
|
1402
|
+
"condition": "$statusCode == 200"
|
|
1403
|
+
}
|
|
1404
|
+
],
|
|
1405
|
+
"outputs": {
|
|
1406
|
+
"senderAuthServer": "$response.body.authServer",
|
|
1407
|
+
"senderResourceServer": "$response.body.resourceServer"
|
|
1408
|
+
}
|
|
1409
|
+
},
|
|
1410
|
+
{
|
|
1411
|
+
"stepId": "requestQuoteGrant",
|
|
1412
|
+
"description": "Request a non-interactive grant from the sender's authorization server to create a quote resource.\n",
|
|
1413
|
+
"operationId": "authServer.post-request",
|
|
1414
|
+
"requestBody": {
|
|
1415
|
+
"contentType": "application/json",
|
|
1416
|
+
"payload": {
|
|
1417
|
+
"access_token": {
|
|
1418
|
+
"access": [
|
|
1419
|
+
{
|
|
1420
|
+
"type": "quote",
|
|
1421
|
+
"actions": [
|
|
1422
|
+
"create",
|
|
1423
|
+
"read"
|
|
1424
|
+
]
|
|
1425
|
+
}
|
|
1426
|
+
]
|
|
1427
|
+
},
|
|
1428
|
+
"client": "$inputs.clientWalletAddress"
|
|
1429
|
+
}
|
|
1430
|
+
},
|
|
1431
|
+
"successCriteria": [
|
|
1432
|
+
{
|
|
1433
|
+
"condition": "$statusCode == 200"
|
|
1434
|
+
}
|
|
1435
|
+
],
|
|
1436
|
+
"outputs": {
|
|
1437
|
+
"quoteAccessToken": "$response.body.access_token.value"
|
|
1438
|
+
}
|
|
1439
|
+
},
|
|
1440
|
+
{
|
|
1441
|
+
"stepId": "createQuote",
|
|
1442
|
+
"description": "Create a quote on the sender's account. The receiver is the URL of the incoming payment. Since the incoming payment has an `incomingAmount`, the quote automatically calculates the debit amount including any fees.\n",
|
|
1443
|
+
"operationId": "resourceServer.create-quote",
|
|
1444
|
+
"requestBody": {
|
|
1445
|
+
"contentType": "application/json",
|
|
1446
|
+
"payload": {
|
|
1447
|
+
"walletAddress": "$inputs.senderWalletAddressUrl",
|
|
1448
|
+
"receiver": "$steps.createIncomingPayment.outputs.incomingPaymentUrl",
|
|
1449
|
+
"method": "ilp"
|
|
1450
|
+
}
|
|
1451
|
+
},
|
|
1452
|
+
"successCriteria": [
|
|
1453
|
+
{
|
|
1454
|
+
"condition": "$statusCode == 201"
|
|
1455
|
+
}
|
|
1456
|
+
],
|
|
1457
|
+
"outputs": {
|
|
1458
|
+
"quoteId": "$response.body.id",
|
|
1459
|
+
"debitAmount": "$response.body.debitAmount",
|
|
1460
|
+
"receiveAmount": "$response.body.receiveAmount",
|
|
1461
|
+
"expiresAt": "$response.body.expiresAt"
|
|
1462
|
+
}
|
|
1463
|
+
},
|
|
1464
|
+
{
|
|
1465
|
+
"stepId": "requestOutgoingPaymentGrant",
|
|
1466
|
+
"description": "Request an interactive grant from the sender's authorization server for the outgoing payment. This returns a redirect URI where the sender must provide explicit consent before the payment can proceed.\n",
|
|
1467
|
+
"operationId": "authServer.post-request",
|
|
1468
|
+
"requestBody": {
|
|
1469
|
+
"contentType": "application/json",
|
|
1470
|
+
"payload": {
|
|
1471
|
+
"access_token": {
|
|
1472
|
+
"access": [
|
|
1473
|
+
{
|
|
1474
|
+
"type": "outgoing-payment",
|
|
1475
|
+
"actions": [
|
|
1476
|
+
"create",
|
|
1477
|
+
"read"
|
|
1478
|
+
],
|
|
1479
|
+
"identifier": "$inputs.senderWalletAddressUrl",
|
|
1480
|
+
"limits": {
|
|
1481
|
+
"debitAmount": "$steps.createQuote.outputs.debitAmount",
|
|
1482
|
+
"receiveAmount": "$steps.createQuote.outputs.receiveAmount",
|
|
1483
|
+
"receiver": "$steps.createIncomingPayment.outputs.incomingPaymentUrl"
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
]
|
|
1487
|
+
},
|
|
1488
|
+
"client": "$inputs.clientWalletAddress",
|
|
1489
|
+
"interact": {
|
|
1490
|
+
"start": [
|
|
1491
|
+
"redirect"
|
|
1492
|
+
],
|
|
1493
|
+
"finish": {
|
|
1494
|
+
"method": "redirect",
|
|
1495
|
+
"uri": "$inputs.finishUri",
|
|
1496
|
+
"nonce": "$inputs.finishNonce"
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
},
|
|
1501
|
+
"successCriteria": [
|
|
1502
|
+
{
|
|
1503
|
+
"condition": "$statusCode == 200"
|
|
1504
|
+
}
|
|
1505
|
+
],
|
|
1506
|
+
"outputs": {
|
|
1507
|
+
"interactRedirectUri": "$response.body.interact.redirect",
|
|
1508
|
+
"interactFinishNonce": "$response.body.interact.finish",
|
|
1509
|
+
"continueAccessToken": "$response.body.continue.access_token.value",
|
|
1510
|
+
"continueUri": "$response.body.continue.uri",
|
|
1511
|
+
"continueWait": "$response.body.continue.wait"
|
|
1512
|
+
}
|
|
1513
|
+
},
|
|
1514
|
+
{
|
|
1515
|
+
"stepId": "continueOutgoingPaymentGrant",
|
|
1516
|
+
"description": "After the sender has completed the interaction (consented to the payment via the identity provider), the client continues the grant request to obtain the access token for the outgoing payment. The client MUST verify the interaction hash before making this call.\n",
|
|
1517
|
+
"operationId": "authServer.post-continue",
|
|
1518
|
+
"parameters": [
|
|
1519
|
+
{
|
|
1520
|
+
"name": "id",
|
|
1521
|
+
"in": "path",
|
|
1522
|
+
"value": "$steps.requestOutgoingPaymentGrant.outputs.continueUri"
|
|
1523
|
+
}
|
|
1524
|
+
],
|
|
1525
|
+
"requestBody": {
|
|
1526
|
+
"contentType": "application/json",
|
|
1527
|
+
"payload": {
|
|
1528
|
+
"interact_ref": "{interact_ref_from_redirect}"
|
|
1529
|
+
}
|
|
1530
|
+
},
|
|
1531
|
+
"successCriteria": [
|
|
1532
|
+
{
|
|
1533
|
+
"condition": "$statusCode == 200"
|
|
1534
|
+
}
|
|
1535
|
+
],
|
|
1536
|
+
"outputs": {
|
|
1537
|
+
"outgoingPaymentAccessToken": "$response.body.access_token.value",
|
|
1538
|
+
"outgoingPaymentManageUrl": "$response.body.access_token.manage"
|
|
1539
|
+
}
|
|
1540
|
+
},
|
|
1541
|
+
{
|
|
1542
|
+
"stepId": "createOutgoingPayment",
|
|
1543
|
+
"description": "Create the outgoing payment resource on the sender's account using the quote ID. This instructs the sender's ASE to execute the payment. The payment setup is now complete — the actual money movement happens on the underlying payment rails between the two ASEs.\n",
|
|
1544
|
+
"operationId": "resourceServer.create-outgoing-payment",
|
|
1545
|
+
"requestBody": {
|
|
1546
|
+
"contentType": "application/json",
|
|
1547
|
+
"payload": {
|
|
1548
|
+
"walletAddress": "$inputs.senderWalletAddressUrl",
|
|
1549
|
+
"quoteId": "$steps.createQuote.outputs.quoteId"
|
|
1550
|
+
}
|
|
1551
|
+
},
|
|
1552
|
+
"successCriteria": [
|
|
1553
|
+
{
|
|
1554
|
+
"condition": "$statusCode == 201"
|
|
1555
|
+
}
|
|
1556
|
+
],
|
|
1557
|
+
"outputs": {
|
|
1558
|
+
"outgoingPaymentId": "$response.body.id",
|
|
1559
|
+
"outgoingPaymentFailed": "$response.body.failed",
|
|
1560
|
+
"sentAmount": "$response.body.sentAmount"
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
],
|
|
1564
|
+
"outputs": {
|
|
1565
|
+
"incomingPaymentUrl": "$steps.createIncomingPayment.outputs.incomingPaymentUrl",
|
|
1566
|
+
"quoteId": "$steps.createQuote.outputs.quoteId",
|
|
1567
|
+
"outgoingPaymentId": "$steps.createOutgoingPayment.outputs.outgoingPaymentId",
|
|
1568
|
+
"debitAmount": "$steps.createQuote.outputs.debitAmount",
|
|
1569
|
+
"receiveAmount": "$steps.createQuote.outputs.receiveAmount"
|
|
1570
|
+
}
|
|
1571
|
+
};
|
|
1572
|
+
const result = await executeWorkflow(workflow, {
|
|
1573
|
+
inputs: inputs,
|
|
1574
|
+
serverUrls: this.serverUrls,
|
|
1575
|
+
authProvider: this.authProvider,
|
|
1576
|
+
hooks: this.hooks,
|
|
1577
|
+
interactionHandler: this.interactionHandler,
|
|
1578
|
+
});
|
|
1579
|
+
if (!result.success) {
|
|
1580
|
+
throw new Error(`Workflow "oneTimePaymentFixedReceive" failed: ${result.error || 'Unknown error'}`);
|
|
1581
|
+
}
|
|
1582
|
+
return {
|
|
1583
|
+
...result.outputs,
|
|
1584
|
+
_raw: result,
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
//# sourceMappingURL=open-payments-client.js.map
|