1+ import type { CID } from 'multiformats'
2+
3+ export type { CID }
4+
5+ /**
6+ * Define nominal type of U based on type of T. Similar to Opaque types in Flow
7+ */
8+ export type Tagged < T , Tag > = T & { tag ?: Tag }
9+
110export interface Service {
211 endpoint : URL
312 token : string
@@ -10,9 +19,29 @@ export interface PublicService {
1019/**
1120 * CID in string representation
1221 */
13- export type CIDString = string & { }
22+ export type CIDString = Tagged < string , CID >
1423
1524export interface API {
25+ /**
26+ * Stores the given token and all resources it references (in the form of a
27+ * File or a Blob) along with a metadata JSON as specificed in ERC-1155. The
28+ * `token.image` must be either a `File` or a `Blob` instance, which will be
29+ * stored and the corresponding content address URL will be saved in the
30+ * metadata JSON file under `image` field.
31+ *
32+ * If `token.properties` contains properties with `File` or `Blob` values,
33+ * those also get stored and their URLs will be saved in the metadata JSON
34+ * file in their place.
35+ *
36+ * Note: URLs for `File` objects will retain file names e.g. in case of
37+ * `new File([bytes], 'cat.png', { type: 'image/png' })` will be transformed
38+ * into a URL that looks like `ipfs://bafy...hash/image/cat.png`. For `Blob`
39+ * objects, the URL will not have a file name name or mime type, instead it
40+ * will be transformed into a URL that looks like
41+ * `ipfs://bafy...hash/image/blob`.
42+ */
43+ store < T extends TokenInput > ( service : Service , token : T ) : Promise < Token < T > >
44+
1645 /**
1746 * Stores a single file and returns a corresponding CID.
1847 */
@@ -137,3 +166,149 @@ export interface Pin {
137166}
138167
139168export type PinStatus = 'queued' | 'pinning' | 'pinned' | 'failed'
169+
170+ /**
171+ * This is an input used to construct the Token metadata as per EIP-1155
172+ * @see https://eips.ethereum.org/EIPS/eip-1155#metadata
173+ */
174+ export interface TokenInput {
175+ /**
176+ * Identifies the asset to which this token represents
177+ */
178+ name : string
179+ /**
180+ * Describes the asset to which this token represents
181+ */
182+ description : string
183+ /**
184+ * A `File` with mime type `image/*` representing the asset this
185+ * token represents. Consider creating images with width between `320` and
186+ * `1080` pixels and aspect ratio between `1.91:1` and `4:5` inclusive.
187+ *
188+ * If a `File` object is used, the URL in the metadata will include a filename
189+ * e.g. `ipfs://bafy...hash/cat.png`. If a `Blob` is used, the URL in the
190+ * metadata will not include filename or extension e.g. `ipfs://bafy...img/`
191+ */
192+ image : Blob | File
193+
194+ /**
195+ * The number of decimal places that the token amount should display - e.g.
196+ * `18`, means to divide the token amount by `1000000000000000000` to get its
197+ * user representation.
198+ */
199+ decimals ?: number
200+
201+ /**
202+ * Arbitrary properties. Values may be strings, numbers, nested objects or
203+ * arrays of values. It is possible to provide `File` or `Blob` instances
204+ * as property values, which will be stored on IPFS, and metadata will
205+ * contain URLs to them in form of `ipfs://bafy...hash/name.png` or
206+ * `ipfs://bafy...file/` respectively.
207+ */
208+ properties ?: Object
209+
210+ localization ?: Localization
211+ }
212+
213+ interface Localization {
214+ /**
215+ * The URI pattern to fetch localized data from. This URI should contain the
216+ * substring `{locale}` which will be replaced with the appropriate locale
217+ * value before sending the request.
218+ */
219+ uri : string
220+ /**
221+ * The locale of the default data within the base JSON
222+ */
223+ default : string
224+ /**
225+ * The list of locales for which data is available. These locales should
226+ * conform to those defined in the Unicode Common Locale Data Repository
227+ * (http://cldr.unicode.org/).
228+ */
229+ locales : string [ ]
230+ }
231+
232+ export interface Token < T extends TokenInput > {
233+ /**
234+ * CID for the token that encloses all of the files including metadata.json
235+ * for the stored token.
236+ */
237+ ipnft : CIDString
238+
239+ /**
240+ * URL like `ipfs://bafy...hash/meta/data.json` for the stored token metadata.
241+ */
242+ url : EncodedURL
243+
244+ /**
245+ * Actual token data in ERC-1155 format. It matches data passed as `token`
246+ * argument except Files/Blobs are substituted with corresponding `ipfs://`
247+ * URLs.
248+ */
249+ data : Encoded < T , [ [ Blob , URL ] ] >
250+
251+ /**
252+ * Token data just like in `data` field except urls corresponding to
253+ * Files/Blobs are substituted with IPFS gateway URLs so they can be
254+ * embedded in browsers that do not support `ipfs://` protocol.
255+ */
256+ embed ( ) : Encoded < T , [ [ Blob , URL ] ] >
257+ }
258+
259+ export type EncodedError = {
260+ message : string
261+ }
262+ export type EncodedURL = Tagged < string , URL >
263+
264+ export type Result < X , T > = { ok : true ; value : T } | { ok : false ; error : X }
265+
266+ export interface EncodedToken < T extends TokenInput > {
267+ ipnft : CIDString
268+ url : EncodedURL
269+ data : Encoded < T , [ [ Blob , EncodedURL ] ] >
270+ }
271+ export type StoreResponse < T extends TokenInput > = Result <
272+ EncodedError ,
273+ EncodedToken < T >
274+ >
275+
276+ /**
277+ * Represents `T` encoded with a given `Format`.
278+ * @example
279+ * ```ts
280+ * type Format = [
281+ * [URL, { type: 'URL', href: string }]
282+ * [CID, { type: 'CID', cid: string }]
283+ * [Blob, { type: 'Blob', href: string }]
284+ * ]
285+ *
286+ * type Response<T> = Encoded<T, Format>
287+ * ```
288+ */
289+ export type Encoded < T , Format extends Pattern < any , any > [ ] > = MatchRecord <
290+ T ,
291+ Rule < Format [ number ] >
292+ >
293+
294+ /**
295+ * Format consists of multiple encoding defines what input type `I` maps to what output type `O`. It
296+ * can be represented via function type or a [I, O] tuple.
297+ */
298+ type Pattern < I , O > = ( ( input : I ) => O ) | [ I , O ]
299+
300+ export type MatchRecord < T , R extends Rule < any > > = {
301+ [ K in keyof T ] : MatchRule < T [ K ] , R > extends never // R extends {I: T[K], O: infer O} ? O : MatchRecord<T[K], R> //Match<T[K], R>
302+ ? MatchRecord < T [ K ] , R >
303+ : MatchRule < T [ K ] , R >
304+ }
305+
306+ type MatchRule < T , R extends Rule < any > > = R extends ( input : T ) => infer O
307+ ? O
308+ : never
309+
310+ type Rule < Format extends Pattern < any , any > > = Format extends [ infer I , infer O ]
311+ ? ( input : I ) => O
312+ : Format extends ( input : infer I ) => infer O
313+ ? ( input : I ) => O
314+ : never
0 commit comments