Skip to content

Commit a79a416

Browse files
feat: handle errors
1 parent 45be45e commit a79a416

13 files changed

Lines changed: 569 additions & 127 deletions

File tree

packages/snap/openrpc.json

Lines changed: 202 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,25 @@
1919
],
2020
"methods": [
2121
{
22-
"name": "client_signAndSendTransactionWithIntent",
22+
"name": "signAndSendTransactionWithIntent",
2323
"summary": "Sign and send a transaction with verified intent",
2424
"description": "Allows the client (MetaMask) to request the snap to sign and send a transaction with verified intent.\n\n**Process:**\n\n1. **Verify Backend Signature** - Ensures that the payload **{ intent, signature }** was signed by the trusted Swaps API\n2. **Match Transaction to Intent** - Verifies that the transaction performs exactly what the intent describes\n3. **Sign Transaction** - If all validation pass, signs the transaction with the user's account specified in the intent\n4. **Send Transaction** - Sends the transaction to the Solana network",
25+
"paramStructure": "by-name",
2526
"params": [
2627
{
2728
"name": "intent",
28-
"summary": "The user's intent describing the desired swap/bridge operation",
29+
"summary": "The user's swap intent describing the desired operation",
2930
"required": true,
3031
"schema": {
31-
"$ref": "#/components/schemas/Intent"
32+
"$ref": "#/components/schemas/SwapIntent"
3233
}
3334
},
3435
{
3536
"name": "transaction",
3637
"summary": "The base64-encoded transaction to sign and send",
3738
"required": true,
3839
"schema": {
39-
"type": "string"
40+
"$ref": "#/components/schemas/Base64String"
4041
}
4142
},
4243
{
@@ -55,6 +56,29 @@
5556
"$ref": "#/components/schemas/SignAndSendTransactionWithIntentResult"
5657
}
5758
},
59+
"errors": [
60+
{
61+
"$ref": "#/components/errors/MethodNotFound"
62+
},
63+
{
64+
"$ref": "#/components/errors/InvalidParams"
65+
},
66+
{
67+
"$ref": "#/components/errors/InvalidBackendSignature"
68+
},
69+
{
70+
"$ref": "#/components/errors/TransactionIntentMismatch"
71+
},
72+
{
73+
"$ref": "#/components/errors/AccountNotFound"
74+
},
75+
{
76+
"$ref": "#/components/errors/InvalidTransaction"
77+
},
78+
{
79+
"$ref": "#/components/errors/TransactionFailed"
80+
}
81+
],
5882
"examples": [
5983
{
6084
"name": "signAndSendTransactionWithIntentExample",
@@ -64,14 +88,17 @@
6488
"name": "intent",
6589
"value": {
6690
"id": "c76b3834-b9a8-4dfd-91da-72c26a216fb2",
67-
"timestamp": "2021-01-01T00:00:00Z",
68-
"accountId": "9ce0cc70-9c04-48f7-a3dc-d9c1496ac229",
91+
"timestamp": "2025-06-04T14:52:31.307Z",
92+
"type": "swap",
93+
"slippage": 0.01,
6994
"from": {
70-
"assetType": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
95+
"address": "BLw3RweJmfbTapJRgnPRvd962YDjFYAnVGd1p5hmZ5tP",
96+
"asset": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
7197
"amount": "1000000000"
7298
},
7399
"to": {
74-
"assetType": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
100+
"address": "27h6cm6S9ag5y4ASi1a1vbTSKEsQMjEdfvZ6atPjmbuD",
101+
"asset": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
75102
"amount": "161180000"
76103
}
77104
}
@@ -88,20 +115,7 @@
88115
"result": {
89116
"name": "signAndSendTransactionWithIntentResult",
90117
"value": {
91-
"signature": "DuvWiKG54eKcB1s777TgaZWtF9R23sVuEaugRufdXyqhCf6owy5hYqxeL8sa6zoCPVQu3NxxhjWuz91CKgLE6SB",
92-
"intent": {
93-
"id": "c76b3834-b9a8-4dfd-91da-72c26a216fb2",
94-
"timestamp": "2021-01-01T00:00:00Z",
95-
"accountId": "9ce0cc70-9c04-48f7-a3dc-d9c1496ac229",
96-
"from": {
97-
"assetType": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501",
98-
"amount": "1000000000"
99-
},
100-
"to": {
101-
"assetType": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
102-
"amount": "161180000"
103-
}
104-
}
118+
"transactionId": "DuvWiKG54eKcB1s777TgaZWtF9R23sVuEaugRufdXyqhCf6owy5hYqxeL8sa6zoCPVQu3NxxhjWuz91CKgLE6SB"
105119
}
106120
}
107121
}
@@ -114,7 +128,7 @@
114128
"type": "string",
115129
"format": "date-time",
116130
"description": "An ISO 8601 timestamp",
117-
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$",
131+
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$",
118132
"examples": ["2021-01-01T00:00:00Z", "2021-01-01T00:00:00.000Z"]
119133
},
120134
"UuidV4": {
@@ -127,9 +141,14 @@
127141
"6ba7b810-9dad-11d1-80b4-00c04fd430c8"
128142
]
129143
},
130-
"Intent": {
144+
"Base64String": {
145+
"type": "string",
146+
"description": "A base64-encoded string",
147+
"pattern": "^[A-Za-z0-9+/]*={0,2}$"
148+
},
149+
"SwapIntent": {
131150
"type": "object",
132-
"description": "Represents a user's intent to perform a swap or bridge operation",
151+
"description": "Represents a user's intent to perform a swap operation",
133152
"properties": {
134153
"id": {
135154
"$ref": "#/components/schemas/UuidV4",
@@ -139,54 +158,195 @@
139158
"$ref": "#/components/schemas/Iso8601Timestamp",
140159
"description": "ISO 8601 timestamp when the intent was created"
141160
},
142-
"accountId": {
161+
"type": {
143162
"type": "string",
144-
"description": "The identifier of the account to sign the transaction with"
163+
"enum": ["swap"],
164+
"description": "The type of operation - must be 'swap'"
165+
},
166+
"slippage": {
167+
"type": "number",
168+
"description": "Maximum acceptable slippage percentage",
169+
"minimum": 0,
170+
"maximum": 100
145171
},
146172
"from": {
147-
"$ref": "#/components/schemas/AssetAmount",
173+
"$ref": "#/components/schemas/AssetTransfer",
148174
"description": "The asset and amount the user wants to send"
149175
},
150176
"to": {
151-
"$ref": "#/components/schemas/AssetAmount",
177+
"$ref": "#/components/schemas/AssetTransfer",
152178
"description": "The asset and amount the user expects to receive"
153179
}
154180
},
155-
"required": ["id", "timestamp", "accountId", "from", "to"],
181+
"required": ["id", "timestamp", "type", "slippage", "from", "to"],
156182
"additionalProperties": false
157183
},
158-
"AssetAmount": {
184+
"AssetTransfer": {
159185
"type": "object",
160-
"description": "Represents an asset and its amount",
186+
"description": "Represents an asset transfer with address, asset type, and amount",
161187
"properties": {
162-
"assetType": {
188+
"address": {
163189
"type": "string",
164-
"description": "CAIP-19 asset type (e.g., 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501' for SOL)"
190+
"description": "A CAIP-10 account address, i.e., the third part of the CAIP account ID. For example, 'BLw3RweJmfbTapJRgnPRvd962YDjFYAnVGd1p5hmZ5tP'."
191+
},
192+
"asset": {
193+
"type": "string",
194+
"description": "A CAIP-19 asset type identifier, i.e., a human-readable type of asset identifier. For example, 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501'."
165195
},
166196
"amount": {
167197
"type": "string",
168-
"description": "Amount in the asset's smallest unit (e.g., lamports for SOL)"
198+
"description": "Amount in the asset's smallest unit (e.g., lamports for SOL)",
199+
"pattern": "^[0-9]+$"
200+
},
201+
"change": {
202+
"type": "object",
203+
"description": "Optional change address for the transaction",
204+
"properties": {
205+
"address": {
206+
"type": "string",
207+
"description": "CAIP-10 account address for change"
208+
}
209+
},
210+
"required": ["address"],
211+
"additionalProperties": false
169212
}
170213
},
171-
"required": ["assetType", "amount"],
214+
"required": ["address", "asset", "amount"],
172215
"additionalProperties": false
173216
},
174217
"SignAndSendTransactionWithIntentResult": {
175218
"type": "object",
176219
"description": "Result of signing and sending a transaction with intent",
177220
"properties": {
178-
"signature": {
221+
"transactionId": {
179222
"type": "string",
180223
"description": "The transaction signature returned after successful execution on Solana"
181-
},
182-
"intent": {
183-
"$ref": "#/components/schemas/Intent",
184-
"description": "The original intent that was fulfilled, returned for assurance that the intent was fulfilled"
185224
}
186225
},
187-
"required": ["signature", "intent"],
226+
"required": ["transactionId"],
188227
"additionalProperties": false
189228
}
229+
},
230+
"errors": {
231+
"MethodNotFound": {
232+
"code": -32601,
233+
"message": "The method does not exist / is not available.",
234+
"data": {
235+
"type": "object",
236+
"description": "The requested method is not supported by this handler",
237+
"properties": {
238+
"method": {
239+
"type": "string",
240+
"description": "The method that was requested"
241+
}
242+
}
243+
}
244+
},
245+
"InvalidParams": {
246+
"code": -32602,
247+
"message": "Invalid method parameter(s).",
248+
"data": {
249+
"type": "object",
250+
"description": "The parameters provided do not match the expected schema"
251+
}
252+
},
253+
"InvalidBackendSignature": {
254+
"code": -32602,
255+
"message": "Invalid backend signature",
256+
"data": {
257+
"type": "object",
258+
"description": "The backend signature verification failed",
259+
"properties": {
260+
"reason": {
261+
"type": "string",
262+
"enum": [
263+
"signatureVerificationFailed",
264+
"timestampExpired",
265+
"invalidSignatureFormat",
266+
"missingPublicKey"
267+
],
268+
"description": "The specific reason why signature verification failed"
269+
}
270+
}
271+
}
272+
},
273+
"TransactionIntentMismatch": {
274+
"code": -32602,
275+
"message": "Transaction does not match intent",
276+
"data": {
277+
"type": "object",
278+
"description": "The transaction does not perform the operations described in the intent",
279+
"properties": {
280+
"reason": {
281+
"type": "string",
282+
"enum": [
283+
"amountMismatch",
284+
"assetMismatch",
285+
"addressMismatch",
286+
"unexpectedInstructions",
287+
"simulationFailed"
288+
],
289+
"description": "The specific reason why the transaction doesn't match the intent"
290+
}
291+
}
292+
}
293+
},
294+
"AccountNotFound": {
295+
"code": -32602,
296+
"message": "Account not found",
297+
"data": {
298+
"type": "object",
299+
"description": "The account specified in the intent was not found in the keyring",
300+
"properties": {
301+
"address": {
302+
"type": "string",
303+
"description": "The account address that was not found"
304+
}
305+
}
306+
}
307+
},
308+
"InvalidTransaction": {
309+
"code": -32602,
310+
"message": "Invalid transaction",
311+
"data": {
312+
"type": "object",
313+
"description": "The transaction is malformed or cannot be processed",
314+
"properties": {
315+
"reason": {
316+
"type": "string",
317+
"enum": [
318+
"invalidBase64Encoding",
319+
"malformedTransaction",
320+
"invalidTransactionStructure",
321+
"missingRequiredFields"
322+
],
323+
"description": "The specific reason why the transaction is invalid"
324+
}
325+
}
326+
}
327+
},
328+
"TransactionFailed": {
329+
"code": -32603,
330+
"message": "Transaction failed",
331+
"data": {
332+
"type": "object",
333+
"description": "The transaction was rejected by the Solana network",
334+
"properties": {
335+
"reason": {
336+
"type": "string",
337+
"enum": [
338+
"insufficientBalance",
339+
"blockhashExpired",
340+
"accountNotFound",
341+
"programError",
342+
"instructionError",
343+
"simulationFailed"
344+
],
345+
"description": "The specific reason why the transaction failed"
346+
}
347+
}
348+
}
349+
}
190350
}
191351
}
192352
}

packages/snap/src/core/domain/Intent.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)