Skip to content

Commit a940bd5

Browse files
Merge pull request #20 from no-witness-labs/feat/upgrade-modules-1
feat: upgrade module
2 parents 51d25ef + 7d0c613 commit a940bd5

File tree

124 files changed

+20340
-3577
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+20340
-3577
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ docs/out
99
docs/.next
1010
# TypeScript incremental compilation cache
1111
*.tsbuildinfo
12-
.tsbuildinfo/
12+
.tsbuildinfo/
13+
14+
.github/instructions/

flake.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
devShells = forEachSupportedSystem ({ pkgs }: {
2323
default = pkgs.mkShell {
24-
packages = with pkgs; [ nodejs nodePackages.pnpm ];
24+
packages = with pkgs; [ nodejs nodePackages.pnpm bun python3 ];
2525
};
2626
});
2727
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"madge": "^8.0.0",
5454
"prettier": "^3.5.0",
5555
"rimraf": "^6.0.0",
56+
"tsx": "^4.20.3",
5657
"turbo": "^2.0.0",
5758
"typescript": "^5.8.0",
5859
"vitest": "^3.2.4"

packages/evolution/package.json

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,23 @@
3737
"clean": "rm -rf dist .turbo docs"
3838
},
3939
"devDependencies": {
40+
"@dcspark/cardano-multiplatform-lib-nodejs": "^6.2.0",
4041
"@types/dockerode": "^3.3.0",
42+
"@types/libsodium-wrappers-sumo": "^0.7.8",
4143
"tsx": "^4.20.3",
4244
"typescript": "^5.4.0"
4345
},
4446
"dependencies": {
45-
"@effect/platform": "^0.90.0",
46-
"@effect/platform-node": "^0.94.0",
47-
"@scure/base": "^1.1.0",
47+
"@effect/platform-node": "^0.94.1",
48+
"@noble/hashes": "^1.6.0",
49+
"@scure/base": "^1.2.0",
50+
"@scure/bip32": "^1.5.0",
51+
"@scure/bip39": "^1.4.0",
52+
"@types/bip39": "^3.0.4",
53+
"bip39": "^3.1.0",
4854
"dockerode": "^4.0.0",
49-
"effect": "^3.17.3"
55+
"effect": "^3.17.3",
56+
"libsodium-wrappers-sumo": "^0.7.15"
5057
},
5158
"keywords": [
5259
"cardano",

packages/evolution/src/Address.ts

Lines changed: 176 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { Data, Effect, FastCheck, ParseResult, pipe, Schema } from "effect"
1+
import { bech32 } from "@scure/base"
2+
import { Data, Effect as Eff, FastCheck, ParseResult, Schema } from "effect"
23

34
import * as BaseAddress from "./BaseAddress.js"
4-
import * as Bech32 from "./Bech32.js"
55
import * as ByronAddress from "./ByronAddress.js"
66
import * as Bytes from "./Bytes.js"
7-
import { createEncoders } from "./Codec.js"
87
import * as EnterpriseAddress from "./EnterpriseAddress.js"
98
import * as PointerAddress from "./PointerAddress.js"
109
import * as RewardAccount from "./RewardAccount.js"
@@ -99,7 +98,7 @@ export const FromBytes = Schema.transformOrFail(Schema.Uint8ArrayFromSelf, Addre
9998
}
10099
},
101100
decode: (_, __, ast, fromA) =>
102-
Effect.gen(function* () {
101+
Eff.gen(function* () {
103102
const header = fromA[0]
104103
// Extract address type from the upper 4 bits (bits 4-7)
105104
const addressType = header >> 4
@@ -152,10 +151,10 @@ export const FromHex = Schema.compose(Bytes.FromHex, FromBytes)
152151
* @since 2.0.0
153152
* @category schema
154153
*/
155-
export const FromBech32 = Schema.transformOrFail(Schema.typeSchema(Bech32.Bech32Schema), Address, {
154+
export const FromBech32 = Schema.transformOrFail(Schema.String, Address, {
156155
strict: true,
157-
encode: (_, __, ___, toA) =>
158-
Effect.gen(function* () {
156+
encode: (_, __, ast, toA) =>
157+
Eff.gen(function* () {
159158
const bytes = yield* ParseResult.encode(FromBytes)(toA)
160159
let prefix: string
161160
switch (toA._tag) {
@@ -168,13 +167,34 @@ export const FromBech32 = Schema.transformOrFail(Schema.typeSchema(Bech32.Bech32
168167
prefix = toA.networkId === 0 ? "stake_test" : "stake"
169168
break
170169
case "ByronAddress":
171-
prefix = ""
172-
break
170+
return yield* ParseResult.fail(
171+
new ParseResult.Type(ast, toA, "Byron addresses do not support Bech32 encoding")
172+
)
173173
}
174-
const b = yield* ParseResult.decode(Bech32.FromBytes(prefix))(bytes)
175-
return b
174+
const result = yield* Eff.try({
175+
try: () => {
176+
const words = bech32.toWords(bytes)
177+
return bech32.encode(prefix, words, false)
178+
},
179+
catch: (error) => new ParseResult.Type(ast, toA, `Failed to encode Bech32: ${(error as Error).message}`)
180+
})
181+
return result
176182
}),
177-
decode: (fromI) => pipe(ParseResult.encode(Bech32.FromBytes())(fromI), Effect.flatMap(ParseResult.decode(FromBytes)))
183+
decode: (fromA, _, ast) =>
184+
Eff.gen(function* () {
185+
const result = yield* Eff.try({
186+
try: () => {
187+
const decoded = bech32.decode(fromA as any, false)
188+
const bytes = bech32.fromWords(decoded.words)
189+
return new Uint8Array(bytes)
190+
},
191+
catch: (error) => new ParseResult.Type(ast, fromA, `Failed to decode Bech32: ${(error as Error).message}`)
192+
})
193+
return yield* ParseResult.decode(FromBytes)(result)
194+
})
195+
}).annotations({
196+
identifier: "Address.FromBech32",
197+
description: "Transforms Bech32 string to Address"
178198
})
179199

180200
/**
@@ -202,29 +222,156 @@ export const equals = (a: Address, b: Address): boolean => {
202222
}
203223

204224
/**
205-
* FastCheck generator for addresses.
225+
* FastCheck arbitrary for Address instances.
206226
*
207227
* @since 2.0.0
208-
* @category testing
228+
* @category arbitrary
229+
*
209230
*/
210-
export const generator = FastCheck.oneof(
211-
BaseAddress.generator,
212-
EnterpriseAddress.generator,
213-
PointerAddress.generator,
214-
RewardAccount.generator
231+
export const arbitrary = FastCheck.oneof(
232+
BaseAddress.arbitrary,
233+
EnterpriseAddress.arbitrary,
234+
PointerAddress.arbitrary,
235+
RewardAccount.arbitrary
215236
)
216237

238+
// ============================================================================
239+
// Parsing Functions
240+
// ============================================================================
241+
217242
/**
218-
* Codec utilities for addresses.
243+
* Parse an Address from bytes.
219244
*
220245
* @since 2.0.0
221-
* @category encoding/decoding
246+
* @category parsing
222247
*/
223-
export const Codec = createEncoders(
224-
{
225-
bech32: FromBech32,
226-
hex: FromHex,
227-
bytes: FromBytes
228-
},
229-
AddressError
230-
)
248+
export const fromBytes = (bytes: Uint8Array): Address => Eff.runSync(Effect.fromBytes(bytes))
249+
250+
/**
251+
* Parse an Address from hex string.
252+
*
253+
* @since 2.0.0
254+
* @category parsing
255+
*/
256+
export const fromHex = (hex: string): Address => Eff.runSync(Effect.fromHex(hex))
257+
258+
/**
259+
* Parse an Address from Bech32 string.
260+
*
261+
* @since 2.0.0
262+
* @category parsing
263+
*/
264+
export const fromBech32 = (bech32: string): Address => Eff.runSync(Effect.fromBech32(bech32))
265+
266+
// ============================================================================
267+
// Encoding Functions
268+
// ============================================================================
269+
270+
/**
271+
* Convert an Address to bytes.
272+
*
273+
* @since 2.0.0
274+
* @category encoding
275+
*/
276+
export const toBytes = (address: Address): Uint8Array => Eff.runSync(Effect.toBytes(address))
277+
278+
/**
279+
* Convert an Address to hex string.
280+
*
281+
* @since 2.0.0
282+
* @category encoding
283+
*/
284+
export const toHex = (address: Address): string => Eff.runSync(Effect.toHex(address))
285+
286+
/**
287+
* Convert an Address to Bech32 string.
288+
*
289+
* @since 2.0.0
290+
* @category encoding
291+
*/
292+
export const toBech32 = (address: Address): string => Eff.runSync(Effect.toBech32(address))
293+
294+
// ============================================================================
295+
// Effect Namespace - Effect-based Error Handling
296+
// ============================================================================
297+
298+
/**
299+
* Effect-based error handling variants for functions that can fail.
300+
* Returns Effect<Success, Error> for composable error handling.
301+
*
302+
* @since 2.0.0
303+
* @category effect
304+
*/
305+
export namespace Effect {
306+
/**
307+
* Parse an Address from bytes.
308+
*
309+
* @since 2.0.0
310+
* @category parsing
311+
*/
312+
export const fromBytes = (bytes: Uint8Array) =>
313+
Eff.mapError(
314+
Schema.decode(FromBytes)(bytes),
315+
(error) => new AddressError({ message: "Failed to decode Address from bytes", cause: error })
316+
)
317+
318+
/**
319+
* Parse an Address from hex string.
320+
*
321+
* @since 2.0.0
322+
* @category parsing
323+
*/
324+
export const fromHex = (hex: string) =>
325+
Eff.mapError(
326+
Schema.decode(FromHex)(hex),
327+
(error) => new AddressError({ message: "Failed to decode Address from hex", cause: error })
328+
)
329+
330+
/**
331+
* Parse an Address from Bech32 string.
332+
*
333+
* @since 2.0.0
334+
* @category parsing
335+
*/
336+
export const fromBech32 = (bech32: string) =>
337+
Eff.mapError(
338+
Schema.decode(FromBech32)(bech32),
339+
(error) => new AddressError({ message: "Failed to decode Address from Bech32", cause: error })
340+
)
341+
342+
/**
343+
* Convert an Address to bytes.
344+
*
345+
* @since 2.0.0
346+
* @category encoding
347+
*/
348+
export const toBytes = (address: Address) =>
349+
Eff.mapError(
350+
Schema.encode(FromBytes)(address),
351+
(error) => new AddressError({ message: "Failed to encode Address to bytes", cause: error })
352+
)
353+
354+
/**
355+
* Convert an Address to hex string.
356+
*
357+
* @since 2.0.0
358+
* @category encoding
359+
*/
360+
export const toHex = (address: Address) =>
361+
Eff.mapError(
362+
Schema.encode(FromHex)(address),
363+
(error) => new AddressError({ message: "Failed to encode Address to hex", cause: error })
364+
)
365+
366+
/**
367+
* Convert an Address to Bech32 string.
368+
*
369+
* @since 2.0.0
370+
* @category encoding
371+
*/
372+
export const toBech32 = (address: Address) =>
373+
Eff.mapError(
374+
Schema.encode(FromBech32)(address),
375+
(error) => new AddressError({ message: "Failed to encode Address to Bech32", cause: error })
376+
)
377+
}

0 commit comments

Comments
 (0)