https://github.com/ceramicnetwork/nft-did-resolver
https://github.com/ceramicnetwork/nft-did-resolver
Last synced: 9 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/ceramicnetwork/nft-did-resolver
- Owner: ceramicnetwork
- License: other
- Created: 2021-03-21T17:35:38.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2023-03-06T19:20:12.000Z (over 3 years ago)
- Last Synced: 2025-01-22T08:43:46.245Z (over 1 year ago)
- Language: TypeScript
- Size: 2.17 MB
- Stars: 33
- Watchers: 9
- Forks: 12
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# NFT DID Resolver
> NFT is a DID method that uses the Ceramic network to resolve DID documents for NFTs
> See [CIP-94](https://github.com/ceramicnetwork/CIP/blob/main/CIPs/CIP-94/CIP-94.md)
## Getting started
This implementation is still a prototype. Contributions are welcome!
To use a package, you would need to provide three subgraph endpoints for every network you are going to use:
one for blocks, one for ERC721 tokens, another for ERC1155 tokens. You would also need to provide a `skew` that
is a time (in milliseconds) within which a latest block is considered valid. Usually it is a typical block time.
### Installation
```
$ npm install nft-did-resolver
```
### Usage
```typescript
import { getResolver } from 'nft-did-resolver'
import type { NftResolverConfig } from 'nft-did-resolver'
import { Resolver } from 'did-resolver'
import Ceramic from '@ceramicnetwork/http-client'
const ceramic = new Ceramic() // connects to localhost:7007 by default
const config: NftResolverConfig = {
ceramic,
chains: {
'eip155:1': {
blocks: 'https://api.thegraph.com/subgraphs/name/yyong1010/ethereumblocks',
skew: 15000,
assets: {
erc721: 'https://api.thegraph.com/subgraphs/name/sunguru98/mainnet-erc721-subgraph',
erc1155: 'https://api.thegraph.com/subgraphs/name/sunguru98/mainnet-erc1155-subgraph',
},
},
'eip155:4': {
blocks: 'https://api.thegraph.com/subgraphs/name/mul53/rinkeby-blocks',
skew: 15000,
assets: {
erc721: 'https://api.thegraph.com/subgraphs/name/sunguru98/erc721-rinkeby-subgraph',
erc1155: 'https://api.thegraph.com/subgraphs/name/sunguru98/erc1155-rinkeby-subgraph',
},
},
},
}
// getResolver will return an object with a key/value pair of { 'nft': resolver }
// where resolver is a function used by the generic did resolver.
const nftResolver = getResolver(config)
const didResolver = Resolver(nftResolver)
const erc721result = await didResolver.resolve(
'did:nft:eip155:1_erc721:0xb300a43751601bd54ffee7de35929537b28e1488_2'
)
const erc1155result = await didResolver.resolve(
'did:nft:eip155:1_erc1155:0x06eb48572a2ef9a3b230d69ca731330793b65bdc_1'
)
console.log(erc721result, erc1155result)
```
`chains` field in config has [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md) chain identifiers as keys.
Each such `chain` is expected to contain endpoints to ERC721 and/or ERC1155 subgraphs under `assets` field.
Both ERC721 and ERC1155 are supported. Feel free to specify either one or both.
The resolver supports the following networks by default:
- Ethereum mainnet (`eip155:1`),
- Ethereum Rinkeby (`eip155:4`),
- Polygon (formerly Matic) (`eip155:137`).
If you use one of those, you do not have to provide `chains` field.
## Testing
```
$ npm test
```
## Custom Subgraphs
You may specify custom subgraph URLs in the configuration object as shown above in [usage](#usage).
**Note**: custom subgraphs must conform to the below schemas at a _minimum_ for assets to be resolved properly.
**Note**: At the moment, only ERC721 and ERC1155 asset namespaces are supported. However, CAIP2 chains beside ETH,
for instance xDAI, with support for those namespaces _are_ supported, as long as the subgraph schema is the same.
### ERC721:
```gql
type Token @entity {
id: ID!
contract: TokenContract!
owner: Owner!
...
}
type TokenContract @entity {
id: ID!
tokens: [Token!]! @derivedFrom(field: "contract")
...
}
type Owner @entity {
id: ID!
tokens: [Token!]! @derivedFrom(field: "owner")
...
}
```
### ERC1155:
```gql
type Account @entity {
id: ID!
balances: [Balance!]! @derivedFrom(field: "account")
...
}
type TokenRegistry @entity {
id: ID!
tokens: [Token!]! @derivedFrom(field: "registry")
...
}
type Token @entity {
id: ID!
registry: TokenRegistry!
identifier: BigInt!
balances: [Balance!]! @derivedFrom(field: "token")
...
}
type Balance @entity {
id: ID!
token: Token!
account: Account!
...
}
```
For more information on writing schemas for GraphProtocol, check out [their documentation](https://thegraph.com/docs/define-a-subgraph#defining-entities).
## DID Specs
The token DIDs are prefixed with `did:nft:`, and the latter half is a modified CAIP format.
**ERC721** ([CAIP-22](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/CAIP-22.md))
DID: `did:nft:{chainNamespace}:{chainReference}_erc721:{contractAddress}_{tokenId}`
CAIP-22: `{chainNamespace}:{chainReference}/erc721:{contractAddress}/{tokenId}`
**ERC1155** ([CAIP-29](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/CAIP-29.md))
DID: `did:nft:{chainNamespace}:{chainReference}_erc1155:{contractAddress}_{tokenId}`
CAIP-29: `{chainNamespace}:{chainReference}/erc1155:{contractAddress}/{tokenId}`
### Conversions
**DID->CAIP**
```
const caip = did.substr(8).replace(/_/g, '/')
```
**CAIP->DID**
```
const did = `did:nft:${caip.replace(/\//g, '_')
```
There are helpers that help you with the conversion:
```typescript
import { caipToDid, didToCaip, createNftDidUrl } from 'nft-did-resolver'
import { AssetId } from 'caip'
// CAIP -> DID URL
const didUrl = createNftDidUrl({
chainId: 'eip155:1',
namespace: 'erc721',
contract: '0x1234567891234567891234567891234596351156'
tokenId: '1',
})
// If you use `caip` library in your app, consider using sister `caipToDid` function to convert `AssetId` to NFT DID URL.
// DID URL -> CAIP
const assetId1 = didToCaip(didUrl) // eip155:1/erc721:0x1234567891234567891234567891234596351156/1
const assetId2 = didToCaip(didUrlWithTimestamp) // eip155:1/erc721:0x1234567891234567891234567891234596351156/1
```
## Contributing
We are happy to accept small and large contributions. Make sure to check out the [Ceramic specifications](https://github.com/ceramicnetwork/specs) for details of how the protocol works.
## License
Apache-2.0 OR MIT