Smart Contract

MnemonicPoetry

A.1717d6b5ee65530a.MnemonicPoetry

Deployed

4h ago
Mar 01, 2026, 08:27:00 AM UTC

Dependents

0 imports
1import BIP39WordListJa from 0x1717d6b5ee65530a
2
3access(all) contract MnemonicPoetry {
4
5    access(all) event NewMnemonic(mnemonic: Mnemonic)
6    access(all) event NewMnemonicPoem(mnemonicPoem: MnemonicPoem)
7
8    access(all) struct Mnemonic {
9        access(all) let words: [String]
10        access(all) let blockID: [UInt8; 32]
11        access(all) let blockHeight: UInt64
12        access(all) let blockTimestamp: UFix64
13
14        init(
15            words: [String],
16            blockID: [UInt8; 32],
17            blockHeight: UInt64,
18            blockTimestamp: UFix64
19        ) {
20            self.words = words
21            self.blockID = blockID
22            self.blockHeight = blockHeight
23            self.blockTimestamp = blockTimestamp
24        }
25    }
26
27    access(all) struct MnemonicPoem {
28        access(all) let mnemonic: Mnemonic
29        access(all) let poem: String
30
31        init(
32            mnemonic: Mnemonic,
33            poem: String
34        ) {
35            self.mnemonic = mnemonic
36            self.poem = poem
37        }
38    }
39
40    access(all) resource interface PoetryCollectionPublic {
41        access(all) var mnemonics: [Mnemonic]
42        access(all) var poems: [MnemonicPoem]
43        access(all) fun getMnemonic(index: Int): Mnemonic
44        access(all) fun getPoem(index: Int): MnemonicPoem
45    }
46
47    access(all) resource PoetryCollection: PoetryCollectionPublic {
48        access(all) var mnemonics: [Mnemonic]
49        access(all) var poems: [MnemonicPoem]
50
51        init() {
52            self.mnemonics = []
53            self.poems = []
54        }
55
56        access(all) fun getMnemonic(index: Int): Mnemonic {
57            return self.mnemonics[index]
58        }
59
60        access(all) fun getPoem(index: Int): MnemonicPoem {
61            return self.poems[index]
62        }
63
64        access(all) fun findMnemonic(): Mnemonic {
65            let block = getCurrentBlock()
66            let entropyWithChecksum = self.blockIDToEntropyWithChecksum(blockID: block.id)
67            let words = self.entropyWithChecksumToWords(entropyWithChecksum: entropyWithChecksum)
68            let mnemonic = Mnemonic(
69                words: words,
70                blockID: block.id,
71                blockHeight: block.height,
72                blockTimestamp: block.timestamp
73            )
74            self.mnemonics.append(mnemonic)
75            emit NewMnemonic(mnemonic: mnemonic)
76            return mnemonic
77        }
78
79        access(self) fun blockIDToEntropyWithChecksum(blockID: [UInt8; 32]): [UInt8] {
80            var entropy: [UInt8] = []
81            var i = 0
82            while i < 16 {
83                entropy.append(blockID[i] ^ blockID[i + 16])
84                i = i + 1
85            }
86            let checksum = HashAlgorithm.SHA2_256.hash(entropy)[0]
87            var entropyWithChecksum = entropy
88            entropyWithChecksum.append(checksum)
89            return entropyWithChecksum
90        }
91
92        access(self) fun entropyWithChecksumToWords(entropyWithChecksum: [UInt8]): [String] {
93            var words: [String] = []
94            var i = 0
95            while i < 12 {
96                let index = self.extract11Bits(from: entropyWithChecksum, at: i * 11)
97                words.append(BIP39WordListJa.ja[index])
98                i = i + 1
99            }
100            return words
101        }
102
103        access(self) fun extract11Bits(from bytes: [UInt8], at bitPosition: Int): Int {
104            let bytePosition = bitPosition / 8
105            let bitOffset = bitPosition % 8
106
107            var res: UInt32 = 0
108            if bytePosition < bytes.length {
109                res = UInt32(bytes[bytePosition]) << 16
110            }
111            if bytePosition + 1 < bytes.length {
112                res = res | (UInt32(bytes[bytePosition + 1]) << 8)
113            }
114            if bitOffset > 5 && bytePosition + 2 < bytes.length {
115                res = res | UInt32(bytes[bytePosition + 2])
116            }
117
118            res = res >> UInt32(24 - 11 - bitOffset)
119            res = res & 0x7FF
120            return Int(res)
121        }
122
123        access(all) fun writePoem(mnemonic: Mnemonic, poem: String) {
124            let mnemonicPoem = MnemonicPoem(
125                mnemonic: mnemonic,
126                poem: poem
127            )
128            self.poems.append(mnemonicPoem)
129            emit NewMnemonicPoem(mnemonicPoem: mnemonicPoem)
130        }
131    }
132
133    access(all) fun createEmptyPoetryCollection(): @PoetryCollection {
134        return <- create PoetryCollection()
135    }
136}
137