@cardano-slips/flow 0.1.0 → 0.2.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.
Files changed (58) hide show
  1. package/dist/balance-error.d.ts +48 -0
  2. package/dist/balance-error.d.ts.map +1 -0
  3. package/dist/balance-error.js +45 -0
  4. package/dist/balance-error.js.map +1 -0
  5. package/dist/balance.d.ts +54 -0
  6. package/dist/balance.d.ts.map +1 -0
  7. package/dist/balance.js +175 -0
  8. package/dist/balance.js.map +1 -0
  9. package/dist/cip30.d.ts +10 -0
  10. package/dist/cip30.d.ts.map +1 -1
  11. package/dist/cip30.js +16 -0
  12. package/dist/cip30.js.map +1 -1
  13. package/dist/complete-error.d.ts +50 -0
  14. package/dist/complete-error.d.ts.map +1 -0
  15. package/dist/complete-error.js +47 -0
  16. package/dist/complete-error.js.map +1 -0
  17. package/dist/complete.d.ts +58 -0
  18. package/dist/complete.d.ts.map +1 -0
  19. package/dist/complete.js +108 -0
  20. package/dist/complete.js.map +1 -0
  21. package/dist/index.d.ts +16 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +10 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/resolve.d.ts +11 -0
  26. package/dist/resolve.d.ts.map +1 -0
  27. package/dist/resolve.js +21 -0
  28. package/dist/resolve.js.map +1 -0
  29. package/dist/sign-error.d.ts +62 -0
  30. package/dist/sign-error.d.ts.map +1 -0
  31. package/dist/sign-error.js +42 -0
  32. package/dist/sign-error.js.map +1 -0
  33. package/dist/sign.d.ts +38 -0
  34. package/dist/sign.d.ts.map +1 -0
  35. package/dist/sign.js +79 -0
  36. package/dist/sign.js.map +1 -0
  37. package/dist/tokens.css +48 -99
  38. package/dist/utxo.d.ts +16 -0
  39. package/dist/utxo.d.ts.map +1 -0
  40. package/dist/utxo.js +51 -0
  41. package/dist/utxo.js.map +1 -0
  42. package/dist/witness.d.ts +23 -0
  43. package/dist/witness.d.ts.map +1 -0
  44. package/dist/witness.js +101 -0
  45. package/dist/witness.js.map +1 -0
  46. package/package.json +7 -4
  47. package/src/balance-error.ts +77 -0
  48. package/src/balance.ts +285 -0
  49. package/src/cip30.ts +19 -0
  50. package/src/complete-error.ts +83 -0
  51. package/src/complete.ts +198 -0
  52. package/src/index.ts +26 -1
  53. package/src/resolve.ts +40 -0
  54. package/src/sign-error.ts +89 -0
  55. package/src/sign.ts +118 -0
  56. package/src/tokens.css +48 -99
  57. package/src/utxo.ts +70 -0
  58. package/src/witness.ts +132 -0
@@ -0,0 +1,108 @@
1
+ import { compare, decodeTransaction, deriveEffects } from "@cardano-slips/verifier";
2
+ import { Effect, Either } from "effect";
3
+ import { balanceIntent } from "./balance.js";
4
+ import { refuse } from "./complete-error.js";
5
+ import { asResolvedInputs } from "./resolve.js";
6
+ import { signTransaction, submitTransaction } from "./sign.js";
7
+ import { readWalletUtxos } from "./utxo.js";
8
+ import { transactionIdOf } from "./witness.js";
9
+ /** Enough rebuilds to outlast an unlucky moment, few enough that nobody is asked forever. */
10
+ const defaultAttempts = 3;
11
+ const fromHex = (hex) => Uint8Array.from({ length: hex.length / 2 }, (_, index) => Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16));
12
+ const walletUtxos = (api) => Effect.gen(function* () {
13
+ const answered = yield* Effect.tryPromise({
14
+ try: () => api.getUtxos(),
15
+ catch: (cause) => refuse("UnreadableUtxos", "The wallet could not say what it holds.", { cause })
16
+ });
17
+ // `null` is CIP-30's own answer for a wallet with nothing to give.
18
+ const hexes = answered ?? [];
19
+ const read = readWalletUtxos(hexes);
20
+ if (Either.isLeft(read)) {
21
+ return yield* Effect.fail(refuse("UnreadableUtxos", `The wallet's unspent outputs could not be read: ${read.left}`));
22
+ }
23
+ if (read.right.length === 0) {
24
+ return yield* Effect.fail(refuse("NoUtxos", "This wallet holds nothing to pay with."));
25
+ }
26
+ return read.right;
27
+ });
28
+ /**
29
+ * One transaction, from the wallet's outputs to a verdict. The judging happens
30
+ * here rather than at the caller so that no path reaches `signTransaction`
31
+ * without having passed it.
32
+ */
33
+ const buildAndJudge = (request, number) => Effect.gen(function* () {
34
+ const utxos = yield* walletUtxos(request.api);
35
+ const now = (request.now ?? Date.now)();
36
+ const built = yield* balanceIntent({
37
+ intent: request.intent,
38
+ network: request.network,
39
+ changeAddress: request.changeAddress,
40
+ utxos,
41
+ parameters: request.parameters,
42
+ ...(request.rewardBalance === undefined ? {} : { rewardBalance: request.rewardBalance }),
43
+ now
44
+ });
45
+ const transaction = decodeTransaction(fromHex(built.cbor));
46
+ if (Either.isLeft(transaction)) {
47
+ return yield* Effect.fail(refuse("CannotJudge", `This transaction could not be read back: ${transaction.left.message}`));
48
+ }
49
+ const effects = deriveEffects({
50
+ transaction: transaction.right,
51
+ userAddresses: request.userAddresses,
52
+ resolvedInputs: asResolvedInputs(utxos),
53
+ protocolParameters: request.parameters
54
+ });
55
+ if (Either.isLeft(effects)) {
56
+ return yield* Effect.fail(refuse("CannotJudge", `What this transaction does could not be worked out: ${effects.left.message}`));
57
+ }
58
+ const verdict = compare({
59
+ effects: effects.right,
60
+ declared: request.intent,
61
+ changeAddress: request.changeAddress,
62
+ now: BigInt(now),
63
+ protocolParameters: request.parameters
64
+ });
65
+ if (Either.isLeft(verdict)) {
66
+ return yield* Effect.fail(refuse("CannotJudge", `This transaction could not be checked against what was declared: ${verdict.left.message}`));
67
+ }
68
+ if (verdict.right._tag === "mismatch") {
69
+ return yield* Effect.fail(refuse("Blocked", "This transaction does not do what the Slip said it would, so it will not be signed.", {
70
+ reasons: verdict.right.reasons
71
+ }));
72
+ }
73
+ const transactionId = yield* transactionIdOf(built.cbor);
74
+ const attempt = { number, transactionId, effects: effects.right };
75
+ // The caller is what puts these effects in front of a person. If that
76
+ // throws, the person has not seen them, so this fails closed rather than
77
+ // carrying on to a signature — and as a refusal rather than a stack trace.
78
+ yield* Effect.try({
79
+ try: () => request.onAttempt?.(attempt),
80
+ catch: (cause) => refuse("NotShown", "This transaction could not be shown, so it will not be signed.", { cause })
81
+ });
82
+ return { cbor: built.cbor, attempt };
83
+ });
84
+ /**
85
+ * Completes the Slip, or says why not. A submission that failed because an
86
+ * input was spent is the one failure worth repeating: everything else either
87
+ * cannot be helped by a rebuild or is a person having said no.
88
+ */
89
+ export const completeIntent = (request) => Effect.gen(function* () {
90
+ const allowed = Math.max(1, request.attempts ?? defaultAttempts);
91
+ for (let number = 1; number <= allowed; number += 1) {
92
+ const { attempt, cbor } = yield* buildAndJudge(request, number);
93
+ const signed = yield* signTransaction({
94
+ api: request.api,
95
+ transaction: cbor,
96
+ transactionId: attempt.transactionId
97
+ });
98
+ const submitted = yield* Effect.either(submitTransaction(request.api, signed));
99
+ if (Either.isRight(submitted)) {
100
+ return { transactionId: submitted.right, effects: attempt.effects, attempts: number };
101
+ }
102
+ if (submitted.left.refusal !== "InputsSpent") {
103
+ return yield* Effect.fail(submitted.left);
104
+ }
105
+ }
106
+ return yield* Effect.fail(refuse("OutOfAttempts", `The wallet's funds moved every time this was built, ${allowed} times over. Try again in a moment.`));
107
+ });
108
+ //# sourceMappingURL=complete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complete.js","sourceRoot":"","sources":["../src/complete.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,14 +4,29 @@
4
4
  */
5
5
  export type { NetworkId, WalletAddress } from "./address.js";
6
6
  export { readWalletAddress } from "./address.js";
7
+ export type { BalancedTransaction, BalanceInputs, BalancingParameters } from "./balance.js";
8
+ export { balanceIntent } from "./balance.js";
9
+ export type { BalanceRefusal } from "./balance-error.js";
10
+ export { BalanceError, balanceRefusals, slipErrorCodeFor as balanceErrorCodeFor } from "./balance-error.js";
7
11
  export type { CborHex, Cip30Api, Cip30ApiError, Cip30Provider, Paginate, SignedData } from "./cip30.js";
8
- export { apiErrorNames, describeApiError, isCip30Api, isCip30Provider, readApiError, REFUSED } from "./cip30.js";
12
+ export { apiErrorNames, describeApiError, isCip30Api, isCip30Provider, readApiError, REFUSED, txSendErrorNames, txSignErrorNames, USER_DECLINED } from "./cip30.js";
13
+ export type { Attempt, CompletionRequest, Receipt } from "./complete.js";
14
+ export { completeIntent } from "./complete.js";
15
+ export type { CompletionRefusal } from "./complete-error.js";
16
+ export { CompletionError, completionRefusals, slipErrorCodeFor as completionErrorCodeFor } from "./complete-error.js";
9
17
  export type { ConnectedWallet, ConnectOptions } from "./connect.js";
10
18
  export { connectWallet, networkIdFor } from "./connect.js";
11
19
  export type { DiscoveredWallet, WalletHost } from "./discovery.js";
12
20
  export { discoverWallets, findWallet, injectedUnder } from "./discovery.js";
13
21
  export type { KnownWallet } from "./registry.js";
14
22
  export { knownWallet, knownWallets } from "./registry.js";
23
+ export { asResolvedInput, asResolvedInputs } from "./resolve.js";
24
+ export type { SignedTransaction, SignRequest } from "./sign.js";
25
+ export { signTransaction, submitTransaction } from "./sign.js";
26
+ export type { SignRefusal } from "./sign-error.js";
27
+ export { signRefusals, SigningError, slipErrorCodeFor as signErrorCodeFor } from "./sign-error.js";
28
+ export { readWalletUtxos } from "./utxo.js";
15
29
  export type { ConnectRefusal } from "./wallet-error.js";
16
30
  export { connectRefusals, slipErrorCodeFor, WalletConnectError } from "./wallet-error.js";
31
+ export { assembleWitnesses, requireSameBody, transactionIdOf } from "./witness.js";
17
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvG,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAChH,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC1D,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC3E,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACzD,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC3G,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvG,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACd,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,IAAI,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACrH,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC1D,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC3E,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAChE,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC9D,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,IAAI,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACzF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,16 @@
1
1
  export { readWalletAddress } from "./address.js";
2
- export { apiErrorNames, describeApiError, isCip30Api, isCip30Provider, readApiError, REFUSED } from "./cip30.js";
2
+ export { balanceIntent } from "./balance.js";
3
+ export { BalanceError, balanceRefusals, slipErrorCodeFor as balanceErrorCodeFor } from "./balance-error.js";
4
+ export { apiErrorNames, describeApiError, isCip30Api, isCip30Provider, readApiError, REFUSED, txSendErrorNames, txSignErrorNames, USER_DECLINED } from "./cip30.js";
5
+ export { completeIntent } from "./complete.js";
6
+ export { CompletionError, completionRefusals, slipErrorCodeFor as completionErrorCodeFor } from "./complete-error.js";
3
7
  export { connectWallet, networkIdFor } from "./connect.js";
4
8
  export { discoverWallets, findWallet, injectedUnder } from "./discovery.js";
5
9
  export { knownWallet, knownWallets } from "./registry.js";
10
+ export { asResolvedInput, asResolvedInputs } from "./resolve.js";
11
+ export { signTransaction, submitTransaction } from "./sign.js";
12
+ export { signRefusals, SigningError, slipErrorCodeFor as signErrorCodeFor } from "./sign-error.js";
13
+ export { readWalletUtxos } from "./utxo.js";
6
14
  export { connectRefusals, slipErrorCodeFor, WalletConnectError } from "./wallet-error.js";
15
+ export { assembleWitnesses, requireSameBody, transactionIdOf } from "./witness.js";
7
16
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEhH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE3E,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEzD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAE3G,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACd,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,IAAI,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAErH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE1D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE3E,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEhE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAE9D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,IAAI,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACzF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The wallet's own unspent outputs, in the form the verifier's derivation takes
3
+ * them. The engine is handed the value of every input the body spends because
4
+ * it never looks one up (invariant 1) — this is where the client, which does
5
+ * know, says so.
6
+ */
7
+ import type { ResolvedInput } from "@cardano-slips/verifier";
8
+ import type { UTxO } from "@evolution-sdk/evolution";
9
+ export declare const asResolvedInput: (utxo: UTxO.UTxO) => ResolvedInput;
10
+ export declare const asResolvedInputs: (utxos: ReadonlyArray<UTxO.UTxO>) => ReadonlyArray<ResolvedInput>;
11
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAUxE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAA;AAgBpD,eAAO,MAAM,eAAe,GAAI,MAAM,IAAI,CAAC,IAAI,KAAG,aAIhD,CAAA;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,KAAG,aAAa,CAAC,aAAa,CAClE,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { Address, AssetName, Assets, MultiAsset as Multi, PolicyId, Schema, TransactionHash } from "@evolution-sdk/evolution";
2
+ const addressBytes = Schema.encodeSync(Address.FromBytes);
3
+ const multiAssetOf = (assets) => {
4
+ const held = Assets.getMultiAsset(assets);
5
+ if (held === undefined)
6
+ return [];
7
+ return Multi.getPolicyIds(held).map((policyId) => ({
8
+ policyId: PolicyId.toBytes(policyId),
9
+ assets: Multi.getAssetsByPolicy(held, policyId).map(([name, quantity]) => ({
10
+ name: AssetName.toBytes(name),
11
+ quantity
12
+ }))
13
+ }));
14
+ };
15
+ export const asResolvedInput = (utxo) => ({
16
+ input: { transactionId: TransactionHash.toBytes(utxo.transactionId), index: utxo.index },
17
+ address: addressBytes(utxo.address),
18
+ value: { coin: Assets.lovelaceOf(utxo.assets), assets: multiAssetOf(utxo.assets) }
19
+ });
20
+ export const asResolvedInputs = (utxos) => utxos.map(asResolvedInput);
21
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,UAAU,IAAI,KAAK,EACnB,QAAQ,EACR,MAAM,EACN,eAAe,EAChB,MAAM,0BAA0B,CAAA;AAGjC,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;AAEzD,MAAM,YAAY,GAAG,CAAC,MAAqB,EAAc,EAAE;IACzD,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;IACzC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IACjC,OAAO,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACjD,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;QACpC,MAAM,EAAE,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;YACzE,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;YAC7B,QAAQ;SACT,CAAC,CAAC;KACJ,CAAC,CAAC,CAAA;AACL,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAe,EAAiB,EAAE,CAAC,CAAC;IAClE,KAAK,EAAE,EAAE,aAAa,EAAE,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;IACxF,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;IACnC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;CACnF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAA+B,EAAgC,EAAE,CAChG,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Why a transaction was not signed, or not submitted. One error, a closed set
3
+ * of refusals, because the client renders a state per refusal and a state
4
+ * nothing can produce is a screen nobody sees.
5
+ */
6
+ import { type ClientErrorCode } from "@cardano-slips/core";
7
+ import { type Cip30ApiError } from "./cip30.js";
8
+ export type SignRefusal =
9
+ /** The bytes we hold are not a transaction these bytes can be read as. */
10
+ "UnreadableTransaction"
11
+ /** This is not the body the effects were derived from, so nothing may be signed into it. */
12
+ | "WrongBody"
13
+ /** The person said no in the wallet. Not a fault. */
14
+ | "Declined"
15
+ /** The wallet tried to sign and could not, or rejected for a reason of its own. */
16
+ | "SignFailed"
17
+ /** What came back is not a witness set — a whole transaction included. */
18
+ | "UnreadableWitnesses"
19
+ /** The set carries script or datum material the body was never judged with. */
20
+ | "UnexpectedWitnessMaterial"
21
+ /** The set carries no signature, so assembling it would leave the transaction unsigned. */
22
+ | "NoWitnesses"
23
+ /** Submission failed because an input was spent between building and signing. */
24
+ | "InputsSpent"
25
+ /** The validity interval passed before the transaction reached the chain. */
26
+ | "IntervalPassed"
27
+ /** Submission failed for any other reason. */
28
+ | "SubmitFailed"
29
+ /** The wallet submitted, and named a transaction other than the one we assembled. */
30
+ | "WrongTransactionId";
31
+ /**
32
+ * Exhaustive by type: adding a refusal above without listing it here fails to
33
+ * compile, and `test/sign.test.ts` fails if any of them stops being reachable.
34
+ */
35
+ export declare const signRefusals: Readonly<Record<SignRefusal, true>>;
36
+ /**
37
+ * Only the passed interval has a spec code, because only it is a failure of the
38
+ * exchange the spec describes — the intent outlived its own `validUntil`. The
39
+ * rest are states of a wallet or of the chain, and a protocol code on one of
40
+ * those would say the endpoint answered when nothing was ever asked of it
41
+ * (`wallet-error.ts` draws the same line).
42
+ */
43
+ export declare const slipErrorCodeFor: (refusal: SignRefusal) => ClientErrorCode | undefined;
44
+ declare const SigningError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
45
+ readonly _tag: "SigningError";
46
+ } & Readonly<A>;
47
+ /** `cip30` is the wallet's own `{ code, info }`, kept so a decline stays distinguishable from a crash. */
48
+ export declare class SigningError extends SigningError_base<{
49
+ readonly refusal: SignRefusal;
50
+ readonly detail: string;
51
+ readonly cip30?: Cip30ApiError;
52
+ readonly cause?: unknown;
53
+ }> {
54
+ get message(): string;
55
+ get code(): ClientErrorCode | undefined;
56
+ }
57
+ export declare const refuse: (refusal: SignRefusal, detail: string, extra?: {
58
+ readonly cip30?: Cip30ApiError;
59
+ readonly cause?: unknown;
60
+ }) => SigningError;
61
+ export {};
62
+ //# sourceMappingURL=sign-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-error.d.ts","sourceRoot":"","sources":["../src/sign-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAG1D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,MAAM,WAAW;AACrB,0EAA0E;AACxE,uBAAuB;AACzB,4FAA4F;GAC1F,WAAW;AACb,qDAAqD;GACnD,UAAU;AACZ,mFAAmF;GACjF,YAAY;AACd,0EAA0E;GACxE,qBAAqB;AACvB,+EAA+E;GAC7E,2BAA2B;AAC7B,2FAA2F;GACzF,aAAa;AACf,iFAAiF;GAC/E,aAAa;AACf,6EAA6E;GAC3E,gBAAgB;AAClB,8CAA8C;GAC5C,cAAc;AAChB,qFAAqF;GACnF,oBAAoB,CAAA;AAExB;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAY5D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,KAAG,eAAe,GAAG,SACb,CAAA;;;;AAE7D,0GAA0G;AAC1G,qBAAa,YAAa,SAAQ,kBAAiC;IACjE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC;IACA,IAAa,OAAO,IAAI,MAAM,CAE7B;IAED,IAAI,IAAI,IAAI,eAAe,GAAG,SAAS,CAEtC;CACF;AAED,eAAO,MAAM,MAAM,GACjB,SAAS,WAAW,EACpB,QAAQ,MAAM,EACd,QAAO;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,KACvE,YAMC,CAAA"}
@@ -0,0 +1,42 @@
1
+ import { Data } from "effect";
2
+ /**
3
+ * Exhaustive by type: adding a refusal above without listing it here fails to
4
+ * compile, and `test/sign.test.ts` fails if any of them stops being reachable.
5
+ */
6
+ export const signRefusals = {
7
+ UnreadableTransaction: true,
8
+ WrongBody: true,
9
+ Declined: true,
10
+ SignFailed: true,
11
+ UnreadableWitnesses: true,
12
+ UnexpectedWitnessMaterial: true,
13
+ NoWitnesses: true,
14
+ InputsSpent: true,
15
+ IntervalPassed: true,
16
+ SubmitFailed: true,
17
+ WrongTransactionId: true
18
+ };
19
+ /**
20
+ * Only the passed interval has a spec code, because only it is a failure of the
21
+ * exchange the spec describes — the intent outlived its own `validUntil`. The
22
+ * rest are states of a wallet or of the chain, and a protocol code on one of
23
+ * those would say the endpoint answered when nothing was ever asked of it
24
+ * (`wallet-error.ts` draws the same line).
25
+ */
26
+ export const slipErrorCodeFor = (refusal) => refusal === "IntervalPassed" ? "INTENT_EXPIRED" : undefined;
27
+ /** `cip30` is the wallet's own `{ code, info }`, kept so a decline stays distinguishable from a crash. */
28
+ export class SigningError extends Data.TaggedError("SigningError") {
29
+ get message() {
30
+ return this.detail;
31
+ }
32
+ get code() {
33
+ return slipErrorCodeFor(this.refusal);
34
+ }
35
+ }
36
+ export const refuse = (refusal, detail, extra = {}) => new SigningError({
37
+ refusal,
38
+ detail,
39
+ ...(extra.cip30 === undefined ? {} : { cip30: extra.cip30 }),
40
+ ...(extra.cause === undefined ? {} : { cause: extra.cause })
41
+ });
42
+ //# sourceMappingURL=sign-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-error.js","sourceRoot":"","sources":["../src/sign-error.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AA4B7B;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAwC;IAC/D,qBAAqB,EAAE,IAAI;IAC3B,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE,IAAI;IACd,UAAU,EAAE,IAAI;IAChB,mBAAmB,EAAE,IAAI;IACzB,yBAAyB,EAAE,IAAI;IAC/B,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,IAAI;IACpB,YAAY,EAAE,IAAI;IAClB,kBAAkB,EAAE,IAAI;CACzB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAoB,EAA+B,EAAE,CACpF,OAAO,KAAK,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAA;AAE7D,0GAA0G;AAC1G,MAAM,OAAO,YAAa,SAAQ,IAAI,CAAC,WAAW,CAAC,cAAc,CAK/D;IACA,IAAa,OAAO;QAClB,OAAO,IAAI,CAAC,MAAM,CAAA;IACpB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACvC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,OAAoB,EACpB,MAAc,EACd,QAAsE,EAAE,EAC1D,EAAE,CAChB,IAAI,YAAY,CAAC;IACf,OAAO;IACP,MAAM;IACN,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAC5D,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;CAC7D,CAAC,CAAA"}
package/dist/sign.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `signTx` → witness assembly → `submitTx`. CIP-30 returns a **witness set**,
3
+ * never a signed transaction (invariant 4), so the body a person was shown and
4
+ * the body that reaches the chain are joined here or nowhere.
5
+ */
6
+ import { Effect } from "effect";
7
+ import { type CborHex, type Cip30Api } from "./cip30.js";
8
+ import { type SigningError } from "./sign-error.js";
9
+ export type SignRequest = {
10
+ readonly api: Cip30Api;
11
+ /** The complete unsigned transaction. */
12
+ readonly transaction: CborHex;
13
+ /**
14
+ * The id of the body the effects were derived from, from `transactionIdOf`.
15
+ * Required, not derived here: a signature is bound to the body a person was
16
+ * shown, and a function that recomputed the id from the bytes in front of it
17
+ * would bind it to whatever it was handed.
18
+ */
19
+ readonly transactionId: string;
20
+ };
21
+ export type SignedTransaction = {
22
+ /** The body with the witnesses in it: what `submitTx` takes. */
23
+ readonly cbor: CborHex;
24
+ /** Unchanged by signing, because witnesses live outside the body. */
25
+ readonly transactionId: string;
26
+ };
27
+ /**
28
+ * Signs, or says why not. Nothing is asked of the wallet until the transaction
29
+ * is known to be the one the effects were derived from.
30
+ */
31
+ export declare const signTransaction: ({ api, transaction, transactionId }: SignRequest) => Effect.Effect<SignedTransaction, SigningError>;
32
+ /**
33
+ * Submits, and holds the wallet to the transaction it was given: an id other
34
+ * than the one we assembled is a receipt for something else, and showing it
35
+ * would tell a person their transaction is on the chain when another one is.
36
+ */
37
+ export declare const submitTransaction: (api: Cip30Api, signed: SignedTransaction) => Effect.Effect<string, SigningError>;
38
+ //# sourceMappingURL=sign.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../src/sign.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAwC,MAAM,YAAY,CAAA;AAC9F,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAG3D,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;IACtB,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,qEAAqE;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B,CAAA;AASD;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,qCAI7B,WAAW,KAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAwB1D,CAAA;AAsBJ;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,QAAQ,EAAE,QAAQ,iBAAiB,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAoB3G,CAAA"}
package/dist/sign.js ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * `signTx` → witness assembly → `submitTx`. CIP-30 returns a **witness set**,
3
+ * never a signed transaction (invariant 4), so the body a person was shown and
4
+ * the body that reaches the chain are joined here or nowhere.
5
+ */
6
+ import { Effect } from "effect";
7
+ import { readApiError, REFUSED, USER_DECLINED } from "./cip30.js";
8
+ import { refuse } from "./sign-error.js";
9
+ import { assembleWitnesses, requireSameBody } from "./witness.js";
10
+ /** What the wallet said, kept whole so a message names its own cause. */
11
+ const said = (cause) => {
12
+ const error = readApiError(cause);
13
+ if (error === undefined)
14
+ return String(cause);
15
+ return error.info === "" ? `code ${error.code}` : error.info;
16
+ };
17
+ /**
18
+ * Signs, or says why not. Nothing is asked of the wallet until the transaction
19
+ * is known to be the one the effects were derived from.
20
+ */
21
+ export const signTransaction = ({ api, transaction, transactionId }) => Effect.gen(function* () {
22
+ yield* requireSameBody(transaction, transactionId);
23
+ const witnesses = yield* Effect.tryPromise({
24
+ // `partialSign: true`: the wallet signs what it holds keys for and leaves
25
+ // the rest, rather than refusing a transaction a co-signer completes.
26
+ try: () => api.signTx(transaction, true),
27
+ catch: (cause) => {
28
+ const error = readApiError(cause);
29
+ // `-3` is `APIError`'s refusal, which wallets send from `signTx` in
30
+ // practice even though CIP-30 numbers a decline `2` here.
31
+ if (error?.code === USER_DECLINED || error?.code === REFUSED) {
32
+ return refuse("Declined", "The signature was declined in the wallet.", { cip30: error, cause });
33
+ }
34
+ return refuse("SignFailed", `The wallet could not sign this transaction: ${said(cause)}`, {
35
+ ...(error === undefined ? {} : { cip30: error }),
36
+ cause
37
+ });
38
+ }
39
+ });
40
+ const cbor = yield* assembleWitnesses(transaction, witnesses, transactionId);
41
+ return { cbor, transactionId };
42
+ });
43
+ /** The ledger's own name for an input that is no longer there — what the rebuild path watches for. */
44
+ const spentInputs = /BadInputsUTxO/i;
45
+ /** The ledger's name for a transaction that arrived outside its validity interval. */
46
+ const outsideInterval = /OutsideValidityInterval/i;
47
+ const submissionFailure = (cause) => {
48
+ const error = readApiError(cause);
49
+ const detail = said(cause);
50
+ const extra = { ...(error === undefined ? {} : { cip30: error }), cause };
51
+ if (spentInputs.test(detail)) {
52
+ return refuse("InputsSpent", "The wallet's funds moved before this transaction reached the chain.", extra);
53
+ }
54
+ if (outsideInterval.test(detail)) {
55
+ return refuse("IntervalPassed", "This transaction expired before it reached the chain.", extra);
56
+ }
57
+ return refuse("SubmitFailed", `This transaction was not accepted: ${detail}`, extra);
58
+ };
59
+ /**
60
+ * Submits, and holds the wallet to the transaction it was given: an id other
61
+ * than the one we assembled is a receipt for something else, and showing it
62
+ * would tell a person their transaction is on the chain when another one is.
63
+ */
64
+ export const submitTransaction = (api, signed) => Effect.gen(function* () {
65
+ const returned = yield* Effect.tryPromise({
66
+ try: () => api.submitTx(signed.cbor),
67
+ catch: submissionFailure
68
+ });
69
+ // Typed to answer with the id and under no obligation to: reading a method
70
+ // off whatever it did answer would reach a person as a stack trace.
71
+ if (typeof returned !== "string") {
72
+ return yield* Effect.fail(refuse("WrongTransactionId", "The wallet did not name the transaction it submitted."));
73
+ }
74
+ if (returned.toLowerCase() !== signed.transactionId.toLowerCase()) {
75
+ return yield* Effect.fail(refuse("WrongTransactionId", "The wallet submitted a different transaction from the one it was given."));
76
+ }
77
+ return signed.transactionId;
78
+ });
79
+ //# sourceMappingURL=sign.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign.js","sourceRoot":"","sources":["../src/sign.ts"],"names":[],"mappings":"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"}