@cardano-slips/flow 0.1.0 → 0.3.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/README.md +53 -9
- package/dist/address.d.ts +12 -0
- package/dist/address.d.ts.map +1 -1
- package/dist/address.js +43 -0
- package/dist/address.js.map +1 -1
- package/dist/balance-error.d.ts +48 -0
- package/dist/balance-error.d.ts.map +1 -0
- package/dist/balance-error.js +45 -0
- package/dist/balance-error.js.map +1 -0
- package/dist/balance.d.ts +54 -0
- package/dist/balance.d.ts.map +1 -0
- package/dist/balance.js +175 -0
- package/dist/balance.js.map +1 -0
- package/dist/card.css +492 -0
- package/dist/card.d.ts +41 -0
- package/dist/card.d.ts.map +1 -0
- package/dist/card.js +69 -0
- package/dist/card.js.map +1 -0
- package/dist/cip30.d.ts +10 -0
- package/dist/cip30.d.ts.map +1 -1
- package/dist/cip30.js +16 -0
- package/dist/cip30.js.map +1 -1
- package/dist/complete-error.d.ts +57 -0
- package/dist/complete-error.d.ts.map +1 -0
- package/dist/complete-error.js +52 -0
- package/dist/complete-error.js.map +1 -0
- package/dist/complete.d.ts +77 -0
- package/dist/complete.d.ts.map +1 -0
- package/dist/complete.js +182 -0
- package/dist/complete.js.map +1 -0
- package/dist/derived.d.ts +8 -0
- package/dist/derived.d.ts.map +1 -0
- package/dist/derived.js +2 -0
- package/dist/derived.js.map +1 -0
- package/dist/effects-panel.d.ts +37 -0
- package/dist/effects-panel.d.ts.map +1 -0
- package/dist/effects-panel.js +64 -0
- package/dist/effects-panel.js.map +1 -0
- package/dist/effects.css +629 -0
- package/dist/exchange.d.ts +54 -0
- package/dist/exchange.d.ts.map +1 -0
- package/dist/exchange.js +136 -0
- package/dist/exchange.js.map +1 -0
- package/dist/explain.d.ts +39 -0
- package/dist/explain.d.ts.map +1 -0
- package/dist/explain.js +172 -0
- package/dist/explain.js.map +1 -0
- package/dist/index.d.ts +34 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/ledger.d.ts +74 -0
- package/dist/ledger.d.ts.map +1 -0
- package/dist/ledger.js +402 -0
- package/dist/ledger.js.map +1 -0
- package/dist/outcome-panel.d.ts +63 -0
- package/dist/outcome-panel.d.ts.map +1 -0
- package/dist/outcome-panel.js +40 -0
- package/dist/outcome-panel.js.map +1 -0
- package/dist/parameter-form.d.ts +26 -0
- package/dist/parameter-form.d.ts.map +1 -0
- package/dist/parameter-form.js +42 -0
- package/dist/parameter-form.js.map +1 -0
- package/dist/resolve.d.ts +11 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +21 -0
- package/dist/resolve.js.map +1 -0
- package/dist/sign-error.d.ts +62 -0
- package/dist/sign-error.d.ts.map +1 -0
- package/dist/sign-error.js +42 -0
- package/dist/sign-error.js.map +1 -0
- package/dist/sign.d.ts +38 -0
- package/dist/sign.d.ts.map +1 -0
- package/dist/sign.js +79 -0
- package/dist/sign.js.map +1 -0
- package/dist/slip-card.d.ts +55 -0
- package/dist/slip-card.d.ts.map +1 -0
- package/dist/slip-card.js +89 -0
- package/dist/slip-card.js.map +1 -0
- package/dist/tokens.css +97 -123
- package/dist/utxo.d.ts +16 -0
- package/dist/utxo.d.ts.map +1 -0
- package/dist/utxo.js +51 -0
- package/dist/utxo.js.map +1 -0
- package/dist/witness.d.ts +23 -0
- package/dist/witness.d.ts.map +1 -0
- package/dist/witness.js +101 -0
- package/dist/witness.js.map +1 -0
- package/package.json +13 -6
- package/src/address.ts +53 -0
- package/src/balance-error.ts +77 -0
- package/src/balance.ts +285 -0
- package/src/card.css +492 -0
- package/src/card.ts +86 -0
- package/src/cip30.ts +19 -0
- package/src/complete-error.ts +95 -0
- package/src/complete.ts +307 -0
- package/src/derived.ts +8 -0
- package/src/effects-panel.tsx +386 -0
- package/src/effects.css +629 -0
- package/src/exchange.ts +212 -0
- package/src/explain.ts +211 -0
- package/src/index.ts +64 -3
- package/src/ledger.ts +503 -0
- package/src/outcome-panel.tsx +263 -0
- package/src/parameter-form.tsx +138 -0
- package/src/resolve.ts +40 -0
- package/src/sign-error.ts +89 -0
- package/src/sign.ts +118 -0
- package/src/slip-card.tsx +244 -0
- package/src/tokens.css +97 -123
- package/src/utxo.ts +70 -0
- package/src/witness.ts +132 -0
package/src/witness.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The transaction id, and the witnesses that may go into the body it names.
|
|
3
|
+
* Pure: nothing here talks to a wallet, so what assembly accepts can be stated
|
|
4
|
+
* as a rule rather than observed against an extension.
|
|
5
|
+
*/
|
|
6
|
+
import { extractTransactionBody } from "@cardano-slips/verifier"
|
|
7
|
+
import { Transaction, TransactionWitnessSet } from "@evolution-sdk/evolution"
|
|
8
|
+
import { blake2b } from "@noble/hashes/blake2.js"
|
|
9
|
+
import { Effect, Either } from "effect"
|
|
10
|
+
|
|
11
|
+
import type { CborHex } from "./cip30.js"
|
|
12
|
+
import { refuse, type SigningError } from "./sign-error.js"
|
|
13
|
+
|
|
14
|
+
const hex = /^[0-9a-fA-F]*$/
|
|
15
|
+
|
|
16
|
+
const bytesOf = (value: CborHex): Uint8Array | undefined => {
|
|
17
|
+
if (value.length % 2 !== 0 || !hex.test(value)) return undefined
|
|
18
|
+
return Uint8Array.from({ length: value.length / 2 }, (_, index) =>
|
|
19
|
+
Number.parseInt(value.slice(index * 2, index * 2 + 2), 16)
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const toHex = (bytes: Uint8Array): string => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("")
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* BLAKE2b-256 over the body's original bytes, never a re-encode: this is the id
|
|
27
|
+
* the chain computes, and it is CIP-0186's commit — what binds a returned
|
|
28
|
+
* witness set to the body whose effects a person was shown.
|
|
29
|
+
*/
|
|
30
|
+
export const transactionIdOf = (transaction: CborHex): Effect.Effect<string, SigningError> => {
|
|
31
|
+
const bytes = bytesOf(transaction)
|
|
32
|
+
if (bytes === undefined) {
|
|
33
|
+
return Effect.fail(refuse("UnreadableTransaction", "This transaction is not readable as CBOR."))
|
|
34
|
+
}
|
|
35
|
+
const body = extractTransactionBody(bytes)
|
|
36
|
+
if (Either.isLeft(body)) {
|
|
37
|
+
return Effect.fail(
|
|
38
|
+
refuse("UnreadableTransaction", `This transaction is not readable: ${body.left.message}`, { cause: body.left })
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
return Effect.succeed(toHex(blake2b(body.right.bodyBytes, { dkLen: 32 })))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* What a version 1 transaction is never signed with. We build nothing that
|
|
46
|
+
* spends from a script, so any of these in a returned set is material the body
|
|
47
|
+
* was not judged with, and merging it would let a wallet add to a transaction
|
|
48
|
+
* after the moment it was shown.
|
|
49
|
+
*/
|
|
50
|
+
const unexpected = (set: TransactionWitnessSet.TransactionWitnessSet): string | undefined => {
|
|
51
|
+
if ((set.nativeScripts ?? []).length > 0) return "native scripts"
|
|
52
|
+
if ((set.bootstrapWitnesses ?? []).length > 0) return "bootstrap witnesses"
|
|
53
|
+
if ((set.plutusV1Scripts ?? []).length > 0) return "Plutus v1 scripts"
|
|
54
|
+
if ((set.plutusV2Scripts ?? []).length > 0) return "Plutus v2 scripts"
|
|
55
|
+
if ((set.plutusV3Scripts ?? []).length > 0) return "Plutus v3 scripts"
|
|
56
|
+
if ((set.plutusData ?? []).length > 0) return "datums"
|
|
57
|
+
if (set.redeemers !== undefined) return "redeemers"
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const readWitnessSet = (witnesses: CborHex): Effect.Effect<TransactionWitnessSet.TransactionWitnessSet, SigningError> =>
|
|
62
|
+
Effect.try({
|
|
63
|
+
try: () => TransactionWitnessSet.fromCBORHex(witnesses),
|
|
64
|
+
catch: (cause) =>
|
|
65
|
+
refuse("UnreadableWitnesses", "The wallet answered with something that is not a witness set.", { cause })
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Refuses unless this is the body the effects were derived from. Asked twice —
|
|
70
|
+
* before the wallet is given anything, and again as assembly begins — because
|
|
71
|
+
* either moment is one where the transaction can stop being the one on screen.
|
|
72
|
+
*/
|
|
73
|
+
export const requireSameBody = (transaction: CborHex, transactionId: string): Effect.Effect<void, SigningError> =>
|
|
74
|
+
Effect.flatMap(transactionIdOf(transaction), (held) =>
|
|
75
|
+
held === transactionId
|
|
76
|
+
? Effect.void
|
|
77
|
+
: Effect.fail(
|
|
78
|
+
refuse("WrongBody", "This is not the transaction the effects were derived from, so it will not be signed.")
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Appends a returned witness set to the body it was asked for, or says why not.
|
|
84
|
+
* `transactionId` is the id the effects were derived from: witnesses go into
|
|
85
|
+
* that body or into none, which is what makes what a person was shown the thing
|
|
86
|
+
* they signed.
|
|
87
|
+
*/
|
|
88
|
+
export const assembleWitnesses = (
|
|
89
|
+
transaction: CborHex,
|
|
90
|
+
witnesses: CborHex,
|
|
91
|
+
transactionId: string
|
|
92
|
+
): Effect.Effect<CborHex, SigningError> =>
|
|
93
|
+
Effect.gen(function* () {
|
|
94
|
+
yield* requireSameBody(transaction, transactionId)
|
|
95
|
+
|
|
96
|
+
const set = yield* readWitnessSet(witnesses)
|
|
97
|
+
|
|
98
|
+
const material = unexpected(set)
|
|
99
|
+
if (material !== undefined) {
|
|
100
|
+
return yield* Effect.fail(
|
|
101
|
+
refuse(
|
|
102
|
+
"UnexpectedWitnessMaterial",
|
|
103
|
+
`The wallet answered with ${material}, which this transaction never asked for.`
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// evolution-sdk returns the transaction untouched for an empty set, so
|
|
109
|
+
// without this an unsigned transaction would go to `submitTx` looking signed.
|
|
110
|
+
if ((set.vkeyWitnesses ?? []).length === 0) {
|
|
111
|
+
return yield* Effect.fail(refuse("NoWitnesses", "The wallet answered without a signature."))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Appends to `vkeyWitnesses` and re-encodes from the format the transaction
|
|
115
|
+
// arrived in, so a co-signer's witness survives and the body keeps its bytes.
|
|
116
|
+
const assembled = yield* Effect.try({
|
|
117
|
+
try: () => Transaction.addVKeyWitnessesHex(transaction, witnesses),
|
|
118
|
+
catch: (cause) =>
|
|
119
|
+
refuse("UnreadableWitnesses", "The wallet's witnesses could not be assembled into the transaction.", { cause })
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
// The body is what the id is taken over, so an id that moved means the
|
|
123
|
+
// bytes moved — and the person would be signing something else.
|
|
124
|
+
const after = yield* transactionIdOf(assembled)
|
|
125
|
+
if (after !== transactionId) {
|
|
126
|
+
return yield* Effect.fail(
|
|
127
|
+
refuse("WrongBody", "Assembling the signature changed the transaction, so it will not be submitted.")
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return assembled
|
|
132
|
+
})
|