@cardano-slips/flow 0.0.3 → 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 (84) hide show
  1. package/README.md +27 -0
  2. package/dist/address.d.ts +13 -0
  3. package/dist/address.d.ts.map +1 -0
  4. package/dist/address.js +54 -0
  5. package/dist/address.js.map +1 -0
  6. package/dist/balance-error.d.ts +48 -0
  7. package/dist/balance-error.d.ts.map +1 -0
  8. package/dist/balance-error.js +45 -0
  9. package/dist/balance-error.js.map +1 -0
  10. package/dist/balance.d.ts +54 -0
  11. package/dist/balance.d.ts.map +1 -0
  12. package/dist/balance.js +175 -0
  13. package/dist/balance.js.map +1 -0
  14. package/dist/cip30.d.ts +76 -0
  15. package/dist/cip30.d.ts.map +1 -0
  16. package/dist/cip30.js +69 -0
  17. package/dist/cip30.js.map +1 -0
  18. package/dist/complete-error.d.ts +50 -0
  19. package/dist/complete-error.d.ts.map +1 -0
  20. package/dist/complete-error.js +47 -0
  21. package/dist/complete-error.js.map +1 -0
  22. package/dist/complete.d.ts +58 -0
  23. package/dist/complete.d.ts.map +1 -0
  24. package/dist/complete.js +108 -0
  25. package/dist/complete.js.map +1 -0
  26. package/dist/connect.d.ts +45 -0
  27. package/dist/connect.d.ts.map +1 -0
  28. package/dist/connect.js +73 -0
  29. package/dist/connect.js.map +1 -0
  30. package/dist/discovery.d.ts +37 -0
  31. package/dist/discovery.d.ts.map +1 -0
  32. package/dist/discovery.js +71 -0
  33. package/dist/discovery.js.map +1 -0
  34. package/dist/index.d.ts +27 -7
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +15 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/registry.d.ts +18 -0
  39. package/dist/registry.d.ts.map +1 -0
  40. package/dist/registry.js +15 -0
  41. package/dist/registry.js.map +1 -0
  42. package/dist/resolve.d.ts +11 -0
  43. package/dist/resolve.d.ts.map +1 -0
  44. package/dist/resolve.js +21 -0
  45. package/dist/resolve.js.map +1 -0
  46. package/dist/sign-error.d.ts +62 -0
  47. package/dist/sign-error.d.ts.map +1 -0
  48. package/dist/sign-error.js +42 -0
  49. package/dist/sign-error.js.map +1 -0
  50. package/dist/sign.d.ts +38 -0
  51. package/dist/sign.d.ts.map +1 -0
  52. package/dist/sign.js +79 -0
  53. package/dist/sign.js.map +1 -0
  54. package/dist/tokens.css +133 -0
  55. package/dist/utxo.d.ts +16 -0
  56. package/dist/utxo.d.ts.map +1 -0
  57. package/dist/utxo.js +51 -0
  58. package/dist/utxo.js.map +1 -0
  59. package/dist/wallet-error.d.ts +48 -0
  60. package/dist/wallet-error.d.ts.map +1 -0
  61. package/dist/wallet-error.js +31 -0
  62. package/dist/wallet-error.js.map +1 -0
  63. package/dist/witness.d.ts +23 -0
  64. package/dist/witness.d.ts.map +1 -0
  65. package/dist/witness.js +101 -0
  66. package/dist/witness.js.map +1 -0
  67. package/package.json +10 -5
  68. package/src/address.ts +69 -0
  69. package/src/balance-error.ts +77 -0
  70. package/src/balance.ts +285 -0
  71. package/src/cip30.ts +113 -0
  72. package/src/complete-error.ts +83 -0
  73. package/src/complete.ts +198 -0
  74. package/src/connect.ts +136 -0
  75. package/src/discovery.ts +92 -0
  76. package/src/index.ts +37 -7
  77. package/src/registry.ts +32 -0
  78. package/src/resolve.ts +40 -0
  79. package/src/sign-error.ts +89 -0
  80. package/src/sign.ts +118 -0
  81. package/src/tokens.css +133 -0
  82. package/src/utxo.ts +70 -0
  83. package/src/wallet-error.ts +68 -0
  84. package/src/witness.ts +132 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Display metadata for the wallets we know by name. Ours to maintain — the one
3
+ * cost ADR-0004 accepted — and deliberately thin: a key an entry does not cover
4
+ * still connects, using the name and icon the extension injects.
5
+ *
6
+ * `install` is the wallet's own home page rather than a store listing, because
7
+ * a store listing is per browser and goes stale on its own schedule.
8
+ */
9
+ export type KnownWallet = {
10
+ readonly key: string;
11
+ readonly name: string;
12
+ readonly install: string;
13
+ /** A second key the same extension injects. Hidden while the primary is present. */
14
+ readonly aliasOf?: string;
15
+ };
16
+ export declare const knownWallets: ReadonlyArray<KnownWallet>;
17
+ export declare const knownWallet: (key: string) => KnownWallet | undefined;
18
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,WAAW,CAWnD,CAAA;AAID,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,WAAW,GAAG,SAA2B,CAAA"}
@@ -0,0 +1,15 @@
1
+ export const knownWallets = [
2
+ { key: "lace", name: "Lace", install: "https://www.lace.io" },
3
+ { key: "eternl", name: "Eternl", install: "https://eternl.io" },
4
+ { key: "ccvault", name: "Eternl", install: "https://eternl.io", aliasOf: "eternl" },
5
+ { key: "vespr", name: "VESPR", install: "https://vespr.xyz" },
6
+ { key: "typhoncip30", name: "Typhon", install: "https://typhonwallet.io" },
7
+ { key: "nami", name: "Nami", install: "https://www.namiwallet.io" },
8
+ { key: "begin", name: "Begin", install: "https://begin.is" },
9
+ { key: "nufi", name: "NuFi", install: "https://nu.fi" },
10
+ { key: "gerowallet", name: "GeroWallet", install: "https://gerowallet.io" },
11
+ { key: "yoroi", name: "Yoroi", install: "https://yoroi-wallet.com" }
12
+ ];
13
+ const byKey = new Map(knownWallets.map((wallet) => [wallet.key, wallet]));
14
+ export const knownWallet = (key) => byKey.get(key);
15
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,YAAY,GAA+B;IACtD,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE;IAC7D,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE;IAC/D,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,QAAQ,EAAE;IACnF,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE;IAC7D,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,yBAAyB,EAAE;IAC1E,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,2BAA2B,EAAE;IACnE,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE;IAC5D,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE;IACvD,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,uBAAuB,EAAE;IAC3E,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,0BAA0B,EAAE;CACrE,CAAA;AAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;AAEzE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAW,EAA2B,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,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":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAA+B,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9F,OAAO,EAAE,MAAM,EAAqB,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAsBjE,yEAAyE;AACzE,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE;IACtC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IAC7C,OAAO,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAA;AAC9D,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAC9B,GAAG,EACH,WAAW,EACX,aAAa,EACD,EAAkD,EAAE,CAChE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,KAAK,CAAC,CAAC,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;IAElD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;QACzC,0EAA0E;QAC1E,sEAAsE;QACtE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC;QACxC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;YACf,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;YACjC,oEAAoE;YACpE,0DAA0D;YAC1D,IAAI,KAAK,EAAE,IAAI,KAAK,aAAa,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC7D,OAAO,MAAM,CAAC,UAAU,EAAE,2CAA2C,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;YACjG,CAAC;YACD,OAAO,MAAM,CAAC,YAAY,EAAE,+CAA+C,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE;gBACxF,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;gBAChD,KAAK;aACN,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;IAEF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,WAAW,EAAE,SAAS,EAAE,aAAa,CAAC,CAAA;IAC5E,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAA;AAChC,CAAC,CAAC,CAAA;AAEJ,sGAAsG;AACtG,MAAM,WAAW,GAAG,gBAAgB,CAAA;AAEpC,sFAAsF;AACtF,MAAM,eAAe,GAAG,0BAA0B,CAAA;AAElD,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAgB,EAAE;IACzD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IACjC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1B,MAAM,KAAK,GAAG,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAA;IAEzE,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,aAAa,EAAE,qEAAqE,EAAE,KAAK,CAAC,CAAA;IAC5G,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,gBAAgB,EAAE,uDAAuD,EAAE,KAAK,CAAC,CAAA;IACjG,CAAC;IACD,OAAO,MAAM,CAAC,cAAc,EAAE,sCAAsC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAA;AACtF,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAa,EAAE,MAAyB,EAAuC,EAAE,CACjH,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;QACxC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;QACpC,KAAK,EAAE,iBAAiB;KACzB,CAAC,CAAA;IAEF,2EAA2E;IAC3E,oEAAoE;IACpE,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,uDAAuD,CAAC,CAAC,CAAA;IAClH,CAAC;IAED,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,MAAM,CAAC,oBAAoB,EAAE,yEAAyE,CAAC,CACxG,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAC,aAAa,CAAA;AAC7B,CAAC,CAAC,CAAA"}
@@ -0,0 +1,133 @@
1
+ /*
2
+ * Every colour, type role, step of spacing and radius the client uses, taken
3
+ * from `1 · Tokens` on the design sheet. This is the only file in the package
4
+ * that writes a colour — `test/no-hard-coded-colours.test.ts` fails if another
5
+ * one does, and `test/tokens.test.ts` re-runs the contrast audit against these
6
+ * values rather than trusting the numbers printed on the sheet.
7
+ *
8
+ * Scoped to a class, never `:root`: this ships into pages we do not own, and a
9
+ * package that writes tokens onto the document redefines whatever the host
10
+ * already called `--ink`. Put `slip-root` on the element that wraps the Slip.
11
+ *
12
+ * There is no reset here and no rule that selects an element. Nothing sets a
13
+ * font-family on anything — a component reads `var(--font-text)` — so a host
14
+ * page's own stack stays where it is until something of ours asks for a token.
15
+ *
16
+ * One theme. The sheet collapsed an earlier light/dark pair into a single
17
+ * ground that leans light, so there is no `data-theme` and no role that means
18
+ * two things. What carries the weight instead is that the three surface
19
+ * families are genuinely different surfaces:
20
+ *
21
+ * page / card the ordinary ground, and what lifts off it
22
+ * vault-* the transaction preview, on slate — the one grave surface,
23
+ * and the reason the rest can stay bright
24
+ * dark-* code blocks and the Open Graph card, fixed wherever they
25
+ * appear because neither sits on a ground we control
26
+ */
27
+
28
+ .slip-root {
29
+ color-scheme: light;
30
+
31
+ /* Surfaces. Depth is a border, never a shadow: there is no shadow token. */
32
+ --page: #ebeef8; /* never pure white */
33
+ --card: #fcfdff;
34
+ --subtle: rgba(90, 110, 205, 0.09); /* hover, chips */
35
+ --skeleton: rgba(90, 110, 205, 0.14);
36
+ --border: rgba(20, 26, 40, 0.13);
37
+ --divider: rgba(20, 26, 40, 0.1);
38
+
39
+ /* Ink */
40
+ --ink: #141a26;
41
+ --muted: #56628a;
42
+
43
+ /*
44
+ * The split rule: --accent-fill is a fill and never carries text below 24px.
45
+ * An accent-coloured word uses --accent-text. It clears AA on the vault and
46
+ * is still held to fills there, because the rule is about what the colour is
47
+ * for and not about the ratio it happens to reach.
48
+ */
49
+ --accent-fill: #728ef3;
50
+ --accent-text: #2f4bc4; /* links */
51
+ --accent-action: #4361e8; /* button background */
52
+ --accent-hover: #2f4bc4;
53
+ --accent-deep: #0c288d; /* headings */
54
+ --on-accent: #ffffff; /* anything drawn on --accent-action */
55
+ --focus: #4361e8;
56
+
57
+ /* Semantic, and rare. A page that colours everything says nothing. */
58
+ --pos: #1f7a5c; /* positive, refundable */
59
+ --warn: #8c5a12;
60
+ --bad: #b3261e;
61
+ --bad-tint: rgba(179, 38, 30, 0.06);
62
+ --bad-line: rgba(179, 38, 30, 0.24);
63
+ --warn-tint: rgba(233, 180, 76, 0.16);
64
+ --warn-line: rgba(233, 180, 76, 0.5);
65
+
66
+ /* The alternating rows of the effects list, on and off. */
67
+ --stripe-a: rgba(90, 110, 205, 0.16);
68
+ --stripe-b: rgba(90, 110, 205, 0.05);
69
+ --stripe-off-a: rgba(86, 98, 138, 0.12);
70
+ --stripe-off-b: rgba(86, 98, 138, 0.04);
71
+
72
+ /*
73
+ * The transaction preview. Its own family because it is the surface that
74
+ * judges the publisher, and `13 · Chrome rules` fixes it whoever hosts the
75
+ * page. Slate rather than black: it has to read as a distinct surface, not
76
+ * as a hole in the page.
77
+ */
78
+ --vault: #222b3d;
79
+ --vault-ink: #f5f7ff;
80
+ --vault-muted: #c3cdec;
81
+ --vault-surface: rgba(255, 255, 255, 0.09);
82
+ --vault-border: rgba(255, 255, 255, 0.16);
83
+ --vault-chip: rgba(168, 188, 255, 0.22);
84
+ --vault-rule: rgba(168, 188, 255, 0.7);
85
+ --vault-pos: #5fd1a6;
86
+ --vault-warn: #e9b44c;
87
+ --vault-bad: #ffa39b;
88
+ --vault-bad-tint: rgba(255, 163, 155, 0.1);
89
+ --vault-bad-line: rgba(255, 163, 155, 0.45);
90
+ --vault-bad-chip: rgba(255, 163, 155, 0.18);
91
+ --vault-warn-tint: rgba(233, 180, 76, 0.12);
92
+ --vault-warn-line: rgba(233, 180, 76, 0.5);
93
+
94
+ /*
95
+ * Code blocks in the docs and the Open Graph card. Both land on a ground we
96
+ * do not control — a reader's docs theme, someone else's timeline — so they
97
+ * carry their own and do not follow anything.
98
+ */
99
+ --dark-bg: #121721;
100
+ --dark-surface: rgba(255, 255, 255, 0.08);
101
+ --dark-text: #ffffff;
102
+ --dark-muted: #ccd6ff;
103
+
104
+ /* Type. Each stack ends in a generic family, so a missing webfont degrades. */
105
+ --font-display: Poppins, system-ui, sans-serif;
106
+ --font-text: Figtree, system-ui, sans-serif;
107
+ --font-mono: "IBM Plex Mono", ui-monospace, monospace;
108
+
109
+ /* Whole roles, so half a role cannot be applied without the other half. */
110
+ --type-h1: 700 44px/48px var(--font-display);
111
+ --type-h1-tracking: -0.01em;
112
+ --type-card-title: 700 18px/24px var(--font-display);
113
+ --type-numeral: 700 26px/32px var(--font-display); /* a figure is always Poppins 700 */
114
+ --type-body: 500 16px/24px var(--font-text);
115
+ --type-button: 500 14px/20px var(--font-text);
116
+ --type-button-tracking: 0.1px;
117
+ --type-label: 500 13px var(--font-text);
118
+ --type-mono: 400 12px/20px var(--font-mono); /* addresses, hashes, the tx block */
119
+
120
+ /* Spacing, on a 4px base. */
121
+ --space-4: 4px;
122
+ --space-8: 8px;
123
+ --space-12: 12px;
124
+ --space-16: 16px;
125
+ --space-20: 20px;
126
+ --space-24: 24px;
127
+ --space-32: 32px;
128
+ --space-48: 48px;
129
+
130
+ --radius-chip: 6px;
131
+ --radius-control: 8px;
132
+ --radius-card: 12px;
133
+ }
package/dist/utxo.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * CIP-30 hands unspent outputs back as CBOR hex; evolution-sdk's builder takes
3
+ * them typed. The SDK has this conversion — `cip30UtxoFromCBORHex` — but only
4
+ * behind an export path its manifest blocks, so it is the sixth gap of ADR-0004
5
+ * and belongs upstream rather than here.
6
+ */
7
+ import { UTxO } from "@evolution-sdk/evolution";
8
+ import { Either } from "effect";
9
+ import type { CborHex } from "./cip30.js";
10
+ /**
11
+ * Reads what `getUtxos` returned. `Either` and not a throw: this runs on
12
+ * whatever a browser extension chose to send, and one unreadable entry must
13
+ * not take the page down.
14
+ */
15
+ export declare const readWalletUtxos: (hexes: ReadonlyArray<CborHex>) => Either.Either<ReadonlyArray<UTxO.UTxO>, string>;
16
+ //# sourceMappingURL=utxo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.d.ts","sourceRoot":"","sources":["../src/utxo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EASL,IAAI,EACL,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAiCzC;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,aAAa,CAAC,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAY7G,CAAA"}
package/dist/utxo.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * CIP-30 hands unspent outputs back as CBOR hex; evolution-sdk's builder takes
3
+ * them typed. The SDK has this conversion — `cip30UtxoFromCBORHex` — but only
4
+ * behind an export path its manifest blocks, so it is the sixth gap of ADR-0004
5
+ * and belongs upstream rather than here.
6
+ */
7
+ import { Address, AddressEras, Assets, CBOR, Schema, Script, TransactionInput, TransactionOutput, UTxO } from "@evolution-sdk/evolution";
8
+ import { Either } from "effect";
9
+ /** The output's address is era-tagged and a UTxO's is not; the bytes are the same. */
10
+ const toAddressStructure = (tagged) => Schema.decodeSync(Address.FromBytes)(Schema.encodeSync(AddressEras.FromBytes)(tagged));
11
+ const readOne = (hex) => {
12
+ const decoded = CBOR.fromCBORHex(hex);
13
+ if (!Array.isArray(decoded) || decoded.length !== 2) {
14
+ throw new Error("a CIP-30 unspent output is an input and an output, and this is neither");
15
+ }
16
+ const input = TransactionInput.fromCBORBytes(CBOR.toCBORBytes(decoded[0]));
17
+ const output = TransactionOutput.fromCBORBytes(CBOR.toCBORBytes(decoded[1]));
18
+ const amount = output.amount;
19
+ return new UTxO.UTxO({
20
+ transactionId: input.transactionId,
21
+ index: input.index,
22
+ address: toAddressStructure(output.address),
23
+ assets: amount._tag === "WithAssets"
24
+ ? Assets.withMultiAsset(amount.coin, amount.assets)
25
+ : Assets.fromLovelace(amount.coin),
26
+ // A Babbage output carries a datum option and a script; a Shelley one carries
27
+ // a datum hash, which is itself a valid datum option.
28
+ datumOption: output._tag === "BabbageTransactionOutput" ? output.datumOption : output.datumHash,
29
+ scriptRef: output._tag === "BabbageTransactionOutput" && output.scriptRef
30
+ ? Script.fromCBOR(output.scriptRef.bytes)
31
+ : undefined
32
+ });
33
+ };
34
+ /**
35
+ * Reads what `getUtxos` returned. `Either` and not a throw: this runs on
36
+ * whatever a browser extension chose to send, and one unreadable entry must
37
+ * not take the page down.
38
+ */
39
+ export const readWalletUtxos = (hexes) => {
40
+ const utxos = [];
41
+ for (const [index, hex] of hexes.entries()) {
42
+ try {
43
+ utxos.push(readOne(hex));
44
+ }
45
+ catch (cause) {
46
+ return Either.left(`unspent output ${index} could not be read: ${cause instanceof Error ? cause.message : String(cause)}`);
47
+ }
48
+ }
49
+ return Either.right(utxos);
50
+ };
51
+ //# sourceMappingURL=utxo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.js","sourceRoot":"","sources":["../src/utxo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,OAAO,EACP,WAAW,EACX,MAAM,EACN,IAAI,EACJ,MAAM,EACN,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EACjB,IAAI,EACL,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAI/B,sFAAsF;AACtF,MAAM,kBAAkB,GAAG,CAAC,MAA+B,EAAmB,EAAE,CAC9E,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAExF,MAAM,OAAO,GAAG,CAAC,GAAY,EAAa,EAAE;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAA;IAC3F,CAAC;IACD,MAAM,KAAK,GAAG,gBAAgB,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1E,MAAM,MAAM,GAAG,iBAAiB,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5E,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAE5B,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC;QACnB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC;QAC3C,MAAM,EACJ,MAAM,CAAC,IAAI,KAAK,YAAY;YAC1B,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;YACnD,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;QACtC,8EAA8E;QAC9E,sDAAsD;QACtD,WAAW,EAAE,MAAM,CAAC,IAAI,KAAK,0BAA0B,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS;QAC/F,SAAS,EACP,MAAM,CAAC,IAAI,KAAK,0BAA0B,IAAI,MAAM,CAAC,SAAS;YAC5D,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;YACzC,CAAC,CAAC,SAAS;KAChB,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAA6B,EAAmD,EAAE;IAChH,MAAM,KAAK,GAAqB,EAAE,CAAA;IAClC,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,IAAI,CAChB,kBAAkB,KAAK,uBAAuB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACvG,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AAC5B,CAAC,CAAA"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Why a wallet did not reach a usable connection. One error, a closed set of
3
+ * refusals, because the client renders a state per refusal and a state nothing
4
+ * 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 ConnectRefusal =
9
+ /** Nothing is injected under this key. The wallet was uninstalled, or never there. */
10
+ "NotInjected"
11
+ /** Something is under the key that does not implement the connector. */
12
+ | "NotCip30"
13
+ /** The person declined the connection — CIP-30 `APIError` `-3`. Not a fault. */
14
+ | "Refused"
15
+ /** `enable()` rejected for another reason, or returned something that is not the API. */
16
+ | "EnableFailed"
17
+ /** A question the wallet did not answer, or answered with something that is not what it claims. */
18
+ | "Unreadable"
19
+ /** The wallet is on a different network from the one the Slip declares. */
20
+ | "WrongNetwork";
21
+ /**
22
+ * Exhaustive by type: adding a refusal above without listing it here fails to
23
+ * compile, and `test/connect.test.ts` fails if any of them stops being reachable.
24
+ */
25
+ export declare const connectRefusals: Readonly<Record<ConnectRefusal, true>>;
26
+ /**
27
+ * Only the network disagreement has a spec code, because only it is a failure
28
+ * of the exchange the spec describes. The rest are states of a browser
29
+ * extension, and dressing them in a protocol code would say the endpoint
30
+ * answered when nothing was ever sent.
31
+ */
32
+ export declare const slipErrorCodeFor: (refusal: ConnectRefusal) => ClientErrorCode | undefined;
33
+ declare const WalletConnectError_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 & {
34
+ readonly _tag: "WalletConnectError";
35
+ } & Readonly<A>;
36
+ /** `cip30` is the wallet's own `{ code, info }`, kept so a `-3` stays distinguishable from a crash. */
37
+ export declare class WalletConnectError extends WalletConnectError_base<{
38
+ readonly refusal: ConnectRefusal;
39
+ readonly key: string;
40
+ readonly detail: string;
41
+ readonly cip30?: Cip30ApiError;
42
+ }> {
43
+ get message(): string;
44
+ get code(): ClientErrorCode | undefined;
45
+ }
46
+ export declare const refuse: (refusal: ConnectRefusal, key: string, detail: string, cip30?: Cip30ApiError) => WalletConnectError;
47
+ export {};
48
+ //# sourceMappingURL=wallet-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-error.d.ts","sourceRoot":"","sources":["../src/wallet-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,cAAc;AACxB,sFAAsF;AACpF,aAAa;AACf,wEAAwE;GACtE,UAAU;AACZ,gFAAgF;GAC9E,SAAS;AACX,yFAAyF;GACvF,cAAc;AAChB,mGAAmG;GACjG,YAAY;AACd,2EAA2E;GACzE,cAAc,CAAA;AAElB;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,CAOlE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,cAAc,KAAG,eAAe,GAAG,SACnB,CAAA;;;;AAE1D,uGAAuG;AACvG,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAA;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAC/B,CAAC;IACA,IAAa,OAAO,IAAI,MAAM,CAE7B;IAED,IAAI,IAAI,IAAI,eAAe,GAAG,SAAS,CAEtC;CACF;AAED,eAAO,MAAM,MAAM,GACjB,SAAS,cAAc,EACvB,KAAK,MAAM,EACX,QAAQ,MAAM,EACd,QAAQ,aAAa,KACpB,kBAAiH,CAAA"}
@@ -0,0 +1,31 @@
1
+ import { Data } from "effect";
2
+ /**
3
+ * Exhaustive by type: adding a refusal above without listing it here fails to
4
+ * compile, and `test/connect.test.ts` fails if any of them stops being reachable.
5
+ */
6
+ export const connectRefusals = {
7
+ NotInjected: true,
8
+ NotCip30: true,
9
+ Refused: true,
10
+ EnableFailed: true,
11
+ Unreadable: true,
12
+ WrongNetwork: true
13
+ };
14
+ /**
15
+ * Only the network disagreement has a spec code, because only it is a failure
16
+ * of the exchange the spec describes. The rest are states of a browser
17
+ * extension, and dressing them in a protocol code would say the endpoint
18
+ * answered when nothing was ever sent.
19
+ */
20
+ export const slipErrorCodeFor = (refusal) => refusal === "WrongNetwork" ? "WRONG_NETWORK" : undefined;
21
+ /** `cip30` is the wallet's own `{ code, info }`, kept so a `-3` stays distinguishable from a crash. */
22
+ export class WalletConnectError extends Data.TaggedError("WalletConnectError") {
23
+ get message() {
24
+ return `${this.key}: ${this.detail}`;
25
+ }
26
+ get code() {
27
+ return slipErrorCodeFor(this.refusal);
28
+ }
29
+ }
30
+ export const refuse = (refusal, key, detail, cip30) => new WalletConnectError({ refusal, key, detail, ...(cip30 === undefined ? {} : { cip30 }) });
31
+ //# sourceMappingURL=wallet-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-error.js","sourceRoot":"","sources":["../src/wallet-error.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAkB7B;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAA2C;IACrE,WAAW,EAAE,IAAI;IACjB,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,IAAI;IACb,YAAY,EAAE,IAAI;IAClB,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,IAAI;CACnB,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAuB,EAA+B,EAAE,CACvF,OAAO,KAAK,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAA;AAE1D,uGAAuG;AACvG,MAAM,OAAO,kBAAmB,SAAQ,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAK3E;IACA,IAAa,OAAO;QAClB,OAAO,GAAG,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,CAAA;IACtC,CAAC;IAED,IAAI,IAAI;QACN,OAAO,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACvC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,OAAuB,EACvB,GAAW,EACX,MAAc,EACd,KAAqB,EACD,EAAE,CAAC,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA"}