@reclack/walletkit 0.0.0-stage → 0.1.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 (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -2
  3. package/assets/backpack.webp +0 -0
  4. package/assets/berasig.webp +0 -0
  5. package/assets/bestwallet.webp +0 -0
  6. package/assets/bifrostwallet.webp +0 -0
  7. package/assets/binance.webp +0 -0
  8. package/assets/bitcoincom.webp +0 -0
  9. package/assets/bitget.webp +0 -0
  10. package/assets/bitpay.webp +0 -0
  11. package/assets/bitski.webp +0 -0
  12. package/assets/bitverse.webp +0 -0
  13. package/assets/blockchaincom.webp +0 -0
  14. package/assets/brave.webp +0 -0
  15. package/assets/bybit.webp +0 -0
  16. package/assets/clv.webp +0 -0
  17. package/assets/coin98.webp +0 -0
  18. package/assets/coinbase.webp +0 -0
  19. package/assets/compass.webp +0 -0
  20. package/assets/core.webp +0 -0
  21. package/assets/crypto_com.webp +0 -0
  22. package/assets/ctrl.webp +0 -0
  23. package/assets/dawn.webp +0 -0
  24. package/assets/desig.webp +0 -0
  25. package/assets/enkrypt.webp +0 -0
  26. package/assets/exodus.webp +0 -0
  27. package/assets/foxwallet.webp +0 -0
  28. package/assets/frame.webp +0 -0
  29. package/assets/frontier.webp +0 -0
  30. package/assets/gate.webp +0 -0
  31. package/assets/gemini.webp +0 -0
  32. package/assets/imtoken.webp +0 -0
  33. package/assets/iopay.webp +0 -0
  34. package/assets/kaia.webp +0 -0
  35. package/assets/kaikas.webp +0 -0
  36. package/assets/kraken.webp +0 -0
  37. package/assets/kresuswallet.webp +0 -0
  38. package/assets/ledger.webp +0 -0
  39. package/assets/magiceden.webp +0 -0
  40. package/assets/meco.webp +0 -0
  41. package/assets/metamask.webp +0 -0
  42. package/assets/mew.webp +0 -0
  43. package/assets/nest.webp +0 -0
  44. package/assets/nova.webp +0 -0
  45. package/assets/okto.webp +0 -0
  46. package/assets/okx.webp +0 -0
  47. package/assets/oneinch.webp +0 -0
  48. package/assets/onekey.webp +0 -0
  49. package/assets/phantom.webp +0 -0
  50. package/assets/rabby.webp +0 -0
  51. package/assets/rainbow.webp +0 -0
  52. package/assets/ramper.webp +0 -0
  53. package/assets/ready.webp +0 -0
  54. package/assets/ronin.webp +0 -0
  55. package/assets/safe.webp +0 -0
  56. package/assets/safepal.webp +0 -0
  57. package/assets/solflare.webp +0 -0
  58. package/assets/subwallet.webp +0 -0
  59. package/assets/taho.webp +0 -0
  60. package/assets/talisman.webp +0 -0
  61. package/assets/tokenary.webp +0 -0
  62. package/assets/tokenpocket.webp +0 -0
  63. package/assets/trust-wallet.webp +0 -0
  64. package/assets/uniswap.webp +0 -0
  65. package/assets/universalprofiles.webp +0 -0
  66. package/assets/valora.webp +0 -0
  67. package/assets/wigwam.webp +0 -0
  68. package/assets/xportal.webp +0 -0
  69. package/assets/zeal.webp +0 -0
  70. package/assets/zerion.webp +0 -0
  71. package/custom-elements.json +207 -0
  72. package/dist/abi.d.ts +21 -0
  73. package/dist/abi.d.ts.map +1 -0
  74. package/dist/abi.js +50 -0
  75. package/dist/abi.js.map +1 -0
  76. package/dist/address.d.ts +15 -0
  77. package/dist/address.d.ts.map +1 -0
  78. package/dist/address.js +25 -0
  79. package/dist/address.js.map +1 -0
  80. package/dist/balance.d.ts +78 -0
  81. package/dist/balance.d.ts.map +1 -0
  82. package/dist/balance.js +146 -0
  83. package/dist/balance.js.map +1 -0
  84. package/dist/base58.d.ts +15 -0
  85. package/dist/base58.d.ts.map +1 -0
  86. package/dist/base58.js +52 -0
  87. package/dist/base58.js.map +1 -0
  88. package/dist/catalog-fetch.d.ts +18 -0
  89. package/dist/catalog-fetch.d.ts.map +1 -0
  90. package/dist/catalog-fetch.js +85 -0
  91. package/dist/catalog-fetch.js.map +1 -0
  92. package/dist/catalog.d.ts +57 -0
  93. package/dist/catalog.d.ts.map +1 -0
  94. package/dist/catalog.js +80 -0
  95. package/dist/catalog.js.map +1 -0
  96. package/dist/chains.d.ts +32 -0
  97. package/dist/chains.d.ts.map +1 -0
  98. package/dist/chains.js +103 -0
  99. package/dist/chains.js.map +1 -0
  100. package/dist/config.d.ts +40 -0
  101. package/dist/config.d.ts.map +1 -0
  102. package/dist/config.js +44 -0
  103. package/dist/config.js.map +1 -0
  104. package/dist/deep-links.d.ts +22 -0
  105. package/dist/deep-links.d.ts.map +1 -0
  106. package/dist/deep-links.js +201 -0
  107. package/dist/deep-links.js.map +1 -0
  108. package/dist/device.d.ts +23 -0
  109. package/dist/device.d.ts.map +1 -0
  110. package/dist/device.js +59 -0
  111. package/dist/device.js.map +1 -0
  112. package/dist/element/attributes.d.ts +48 -0
  113. package/dist/element/element.d.ts +92 -0
  114. package/dist/element/index.d.ts +4 -0
  115. package/dist/element/props.d.ts +67 -0
  116. package/dist/element/ui/app.d.ts +22 -0
  117. package/dist/element/ui/assets.d.ts +7 -0
  118. package/dist/element/ui/qr.d.ts +16 -0
  119. package/dist/element/ui/use-handheld.d.ts +8 -0
  120. package/dist/element/ui/wallet-connect-panel.d.ts +26 -0
  121. package/dist/element/ui/wallet-dialog.d.ts +37 -0
  122. package/dist/element/ui/wallet-list.d.ts +26 -0
  123. package/dist/element/ui/wallet-mark.d.ts +15 -0
  124. package/dist/element.js +2079 -0
  125. package/dist/errors.d.ts +34 -0
  126. package/dist/errors.d.ts.map +1 -0
  127. package/dist/errors.js +64 -0
  128. package/dist/errors.js.map +1 -0
  129. package/dist/evm.d.ts +49 -0
  130. package/dist/evm.d.ts.map +1 -0
  131. package/dist/evm.js +217 -0
  132. package/dist/evm.js.map +1 -0
  133. package/dist/icons.d.ts +22 -0
  134. package/dist/icons.d.ts.map +1 -0
  135. package/dist/icons.js +98 -0
  136. package/dist/icons.js.map +1 -0
  137. package/dist/index.d.ts +39 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +43 -0
  140. package/dist/index.js.map +1 -0
  141. package/dist/intent.d.ts +60 -0
  142. package/dist/intent.d.ts.map +1 -0
  143. package/dist/intent.js +2 -0
  144. package/dist/intent.js.map +1 -0
  145. package/dist/kit.d.ts +124 -0
  146. package/dist/kit.d.ts.map +1 -0
  147. package/dist/kit.js +362 -0
  148. package/dist/kit.js.map +1 -0
  149. package/dist/svm.d.ts +45 -0
  150. package/dist/svm.d.ts.map +1 -0
  151. package/dist/svm.js +201 -0
  152. package/dist/svm.js.map +1 -0
  153. package/dist/theme.d.ts +101 -0
  154. package/dist/theme.d.ts.map +1 -0
  155. package/dist/theme.js +217 -0
  156. package/dist/theme.js.map +1 -0
  157. package/dist/types.d.ts +144 -0
  158. package/dist/types.d.ts.map +1 -0
  159. package/dist/types.js +2 -0
  160. package/dist/types.js.map +1 -0
  161. package/dist/wallet-standard.d.ts +77 -0
  162. package/dist/wallet-standard.d.ts.map +1 -0
  163. package/dist/wallet-standard.js +89 -0
  164. package/dist/wallet-standard.js.map +1 -0
  165. package/dist/walletconnect.d.ts +74 -0
  166. package/dist/walletconnect.d.ts.map +1 -0
  167. package/dist/walletconnect.js +133 -0
  168. package/dist/walletconnect.js.map +1 -0
  169. package/package.json +71 -3
  170. package/vscode.html-custom-data.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Reclack
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,342 @@
1
- # Temporary Holding Version
1
+ # @reclack/walletkit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Connect a wallet, read an address, read a balance. No renderer, no framework,
4
+ no wallet SDK.
5
+
6
+ Wallets speak EIP-1193, EIP-6963 and the Wallet Standard, all of which are
7
+ small enough to talk to by hand. A page that handles other people's money
8
+ should ship as little code it did not write as it can, so this talks to them
9
+ directly.
10
+
11
+ One dependency, and only five wallets need it: Safe, Kraken, BitPay,
12
+ Bitcoin.com and Blockchain.com inject nothing into a page, so they are reached
13
+ over a relay. Its provider sits behind a dynamic import and is fetched only
14
+ when one of those is chosen. Everyone else loads none of it.
15
+
16
+ ```sh
17
+ npm install @reclack/walletkit
18
+ ```
19
+
20
+ ## The kit
21
+
22
+ Everything hangs off one object with `getState` and `subscribe`. That pair is
23
+ the only shape every framework agrees on, so this package picks none of them.
24
+
25
+ ```ts
26
+ import { createWalletKit } from '@reclack/walletkit'
27
+
28
+ const kit = createWalletKit()
29
+ const stop = kit.subscribe(() => render(kit.getState()))
30
+ ```
31
+
32
+ No configuration. Which API to read the wallet catalogue from, which relay to
33
+ pair over, which endpoints to read balances from: none of that is a decision a
34
+ page embedding a wallet picker should have to make, so the kit ships with it.
35
+ Options exist for a sandbox, a private endpoint or a partner running the kit
36
+ under its own name, and all of them are overrides rather than requirements.
37
+
38
+ Nothing touches `window` until the first subscriber arrives, so importing this
39
+ on a server is safe and a host that renders on one needs no guards.
40
+
41
+ ### Vanilla
42
+
43
+ ```js
44
+ kit.subscribe(() => {
45
+ const { evm } = kit.getState()
46
+ list.replaceChildren(...evm.available.map(toRow))
47
+ })
48
+ ```
49
+
50
+ ### React
51
+
52
+ ```tsx
53
+ const state = useSyncExternalStore(kit.subscribe, kit.getState, kit.getState)
54
+ ```
55
+
56
+ ### Vue
57
+
58
+ ```ts
59
+ const state = shallowRef(kit.getState())
60
+ onMounted(() => kit.subscribe(() => { state.value = kit.getState() }))
61
+ ```
62
+
63
+ ### Svelte
64
+
65
+ ```ts
66
+ const state = { subscribe: (run) => (run(kit.getState()), kit.subscribe(() => run(kit.getState()))) }
67
+ ```
68
+
69
+ ### Angular
70
+
71
+ ```ts
72
+ readonly state = toSignal(new Observable((s) => kit.subscribe(() => s.next(kit.getState()))))
73
+ ```
74
+
75
+ ## Intent
76
+
77
+ What a caller wants back from connecting, as a list rather than a mode,
78
+ because these are not alternatives.
79
+
80
+ ```ts
81
+ await kit.connectEvm(wallet)
82
+
83
+ const result = await kit.resolveIntent('evm', {
84
+ intent: ['address', 'balance'],
85
+ assets: [{ family: 'evm', chainId: 8453, token: USDC, decimals: 6 }],
86
+ keepAlive: false,
87
+ })
88
+ // { address, chainId, walletId, name, family, balances }
89
+ ```
90
+
91
+ - `address` is the by-product of connecting, so it is always obtained. Asking
92
+ for it says only that the caller wants it handed back.
93
+ - `balance` needs an asset to be a balance of. Asking without one throws: it
94
+ is a mistake in the caller, not a state anybody can connect their way out of.
95
+ - `keepAlive` holds the provider open and keeps following account and chain
96
+ changes. True for a checkout, which signs later. False for a form, which
97
+ wanted a value and is done.
98
+
99
+ A chain is enforced only when `chainId` is given. A page collecting a
100
+ settlement address should leave it out: the same address receives on every EVM
101
+ chain, and asking somebody to switch networks in their wallet to read an
102
+ address back is theatre.
103
+
104
+ ## The element
105
+
106
+ The picker itself, as a custom element. An element is the only component model
107
+ React, Vue, Angular, Svelte and a page with no framework already share, so
108
+ that is what it is.
109
+
110
+ ```html
111
+ <script type="module" src="/path/to/@reclack/walletkit/element"></script>
112
+
113
+ <reclack-connect
114
+ variant="modal"
115
+ family="evm"
116
+ chain-id="8453"
117
+ intent="address,balance"
118
+ theme-mode="system"
119
+ brand="#ff6600"
120
+ asset-base="/wallets/"
121
+ ></reclack-connect>
122
+ ```
123
+
124
+ ```js
125
+ document.querySelector('reclack-connect')
126
+ .addEventListener('connect', (event) => {
127
+ event.detail // { address, chainId, walletId, name, family, balances }
128
+ })
129
+ ```
130
+
131
+ Events are `connect`, `cancel` and `connect-error`, all composed, so a
132
+ listener on an ancestor hears them through the shadow boundary. `connect-error`
133
+ rather than `error`, which already means a resource failed to load.
134
+
135
+ `variant` is `inline`, the short list a checkout puts on the page with the
136
+ full catalogue folded behind one row, or `modal`, the whole picker over the
137
+ page. The modal is a native `<dialog>`: focus trapping, Esc, an inert
138
+ background and a backdrop come from the platform rather than from a focus-trap
139
+ library shipped on a page that takes payments.
140
+
141
+ Markup is in a shadow root, so nothing here can reach the host's page and
142
+ nothing in the page can reach in. The tokens are set on the element itself,
143
+ where a host can still override any single one of them.
144
+
145
+ ### Your framework
146
+
147
+ The tag is `reclack-connect` because a custom element's name must be
148
+ lowercase and contain a hyphen. That is the HTML spec, not a style choice, and
149
+ nobody should have to write it.
150
+
151
+ **React, and anything built on it (Next.js, Remix, React Router):**
152
+
153
+ ```sh
154
+ npm install @reclack/walletkit @reclack/walletkit-react
155
+ ```
156
+
157
+ ```tsx
158
+ import { ReclackConnect } from '@reclack/walletkit-react'
159
+
160
+ <ReclackConnect
161
+ variant="modal"
162
+ family="evm"
163
+ chainId={8453}
164
+ intent={['address']}
165
+ onConnect={({ address }) => setAddress(address)}
166
+ onCancel={() => setOpen(false)}
167
+ />
168
+ ```
169
+
170
+ In Next.js the file needs `'use client'`, because the component uses hooks.
171
+ The kit itself is safe to import on a server: it touches no browser API until
172
+ something subscribes, and registering the element is skipped where there is no
173
+ `customElements`.
174
+
175
+ **Preact:** the same package. Preact's `preact/compat` alias makes React
176
+ components work unchanged, which is how this checkout uses it.
177
+
178
+ **Vue:**
179
+
180
+ ```sh
181
+ npm install @reclack/walletkit @reclack/walletkit-vue
182
+ ```
183
+
184
+ ```vue
185
+ <ReclackConnect variant="modal" family="evm" :chain-id="8453" @connect="onConnect" />
186
+ ```
187
+
188
+ **Angular, Svelte, SolidJS, and plain HTML need no wrapper**, and adding one
189
+ would be ceremony rather than help: all three bind properties and listen to
190
+ custom events on an element natively, which is the whole thing a wrapper does
191
+ for React.
192
+
193
+ ```html
194
+ <!-- Angular, with CUSTOM_ELEMENTS_SCHEMA in the component or module -->
195
+ <reclack-connect [kit]="kit" family="evm" (connect)="onConnect($event)"></reclack-connect>
196
+ ```
197
+
198
+ ```svelte
199
+ <!-- Svelte -->
200
+ <reclack-connect {kit} family="evm" on:connect={(e) => take(e.detail)} />
201
+ ```
202
+
203
+ ```jsx
204
+ /* SolidJS */
205
+ <reclack-connect prop:kit={kit} family="evm" on:connect={(e) => take(e.detail)} />
206
+ ```
207
+
208
+ Editors and Vue's language server read `custom-elements.json`, shipped in this
209
+ package, so the tag and its attributes autocomplete without a wrapper.
210
+ `vscode.html-custom-data.json` does the same for plain HTML.
211
+
212
+ ### One call
213
+
214
+ For a host that only wants a value, filling a settlement address should not
215
+ take an element, two listeners and a piece of state:
216
+
217
+ ```ts
218
+ import { connectWallet } from '@reclack/walletkit/element'
219
+
220
+ const { address } = await connectWallet({ intent: ['address'], family: 'evm' })
221
+ ```
222
+
223
+ It opens the modal, resolves with the result and rejects when the person
224
+ closes it. That is a refusal, not a failure, and a caller that wants to ignore
225
+ it can.
226
+
227
+ ### Sharing a kit
228
+
229
+ Each element makes its own kit unless given one. A page with several pickers
230
+ should share, because discovery is a window listener and a catalogue fetch,
231
+ and a second kit runs both again to answer the same question.
232
+
233
+ ```ts
234
+ element.useKit(myKit)
235
+ ```
236
+
237
+ Themes stay per element even then, so a dashboard can show a light picker in a
238
+ panel and a dark one in a drawer off one kit.
239
+
240
+ ## Theme
241
+
242
+ Twelve tokens, light or dark, and nothing else to override.
243
+
244
+ ```ts
245
+ const kit = createWalletKit({
246
+ theme: {
247
+ mode: 'system', // 'light' | 'dark' | 'system' (the default)
248
+ brand: '#ff6600', // your colour, worn by the primary action
249
+ radius: '14px',
250
+ fontFamily: 'Inter, sans-serif',
251
+ dark: { surface: '#000000' }, // applied on top, in dark only
252
+ },
253
+ })
254
+ ```
255
+
256
+ The resolved mode and the tokens live in the state everything is already
257
+ subscribed to, so when the reader's system flips to dark the picker follows
258
+ without a second listener:
259
+
260
+ ```ts
261
+ const { scheme, variables } = kit.getState()
262
+ // scheme: 'dark'
263
+ // variables: { '--rkw-surface': '#16161a', '--rkw-brand': '#ff6600', ... }
264
+ ```
265
+
266
+ `kit.setTheme(...)` replaces it later, which is what an embedded checkout does
267
+ when a merchant's branding arrives.
268
+
269
+ Three things the kit decides rather than asking:
270
+
271
+ - **Text on the brand colour is computed**, by relative luminance, so a pale
272
+ brand gets dark text instead of the white that would leave the button
273
+ unreadable.
274
+ - **Dark is a chosen palette, not an inverted one.** Inverting gives muddy
275
+ greys and a brand that has stopped contrasting with anything. A brand colour
276
+ a host sets is kept in both modes, though: it is their colour.
277
+ - **A value it cannot read is dropped** and the default stands. Colours must be
278
+ `#rrggbb`. In the embedded checkout the branding comes from an API response
279
+ and ends up inside a style, and a page that takes payment details must not
280
+ interpolate whatever a response happens to carry.
281
+
282
+ And one it decides from whether you set a brand at all: **a row is washed grey
283
+ on hover until you pick a colour**, then in yours. The default brand is
284
+ Reclack's own, and a page nobody has branded should not be hovering in it.
285
+
286
+ Tokens are prefixed `--rkw-` because they are set on an element the host also
287
+ styles. Without a prefix, `--surface` would silently take over or be taken
288
+ over.
289
+
290
+ ## Balances
291
+
292
+ Amounts are `bigint`, in the asset's smallest unit, and `formatUnits` places
293
+ the decimal point with string arithmetic. Money does not survive a float.
294
+
295
+ Where a balance is read from changes what it costs. Through an endpoint,
296
+ several chains can be read at once and no wallet is dragged onto another
297
+ network. Through the connected wallet's own provider, the wallet must already
298
+ be on that chain. So an endpoint is the default, and the provider is for the
299
+ one case that needs it: the pre-flight immediately before signing, where the
300
+ question is what this exact wallet can spend right now.
301
+
302
+ The pinned public endpoints are used unless a host passes its own in
303
+ `rpcUrls`, which is worth doing for anything heavier than a balance or two.
304
+
305
+ Solana is endpoint-only. Solana wallets sign; they do not answer questions
306
+ about the chain.
307
+
308
+ ## Artwork
309
+
310
+ Wallet logos ship in `assets/` as `.webp` files. Copy them into whatever your
311
+ app serves static files from, then say where that is:
312
+
313
+ ```ts
314
+ createWalletKit({ assetBase: '/wallets/' }) // the kit
315
+ ```
316
+
317
+ ```html
318
+ <reclack-connect asset-base="/wallets/"></reclack-connect>
319
+ ```
320
+
321
+ The default is `/images/`. Served by you rather than fetched from us, so a
322
+ checkout still makes no third-party image request, and a wallet's own EIP-6963
323
+ icon wins over these anyway: that is the artwork of the provider actually
324
+ present. Getting the path wrong costs the logos of wallets that are not
325
+ installed, not the ability to connect.
326
+
327
+ ## WalletConnect
328
+
329
+ Safe, Kraken, BitPay, Bitcoin.com and Blockchain.com inject nothing into the
330
+ page, so they are reached over a relay. Nothing to install and nothing to
331
+ configure: the relay provider ships with the kit, behind a dynamic import, so
332
+ only somebody who picks one of those wallets ever downloads it.
333
+
334
+ Pass `walletConnect: { projectId, metadata }` to pair under your own project.
335
+
336
+ ## Build
337
+
338
+ ```sh
339
+ pnpm install
340
+ pnpm test
341
+ pnpm build
342
+ ```
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file