mirror of
https://github.com/oceanprotocol/ocean-subgraph.git
synced 2024-12-02 05:57:29 +01:00
add dispenser (#106)
* add dispenser Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro> Co-authored-by: Jamie Hewitt <jamie.hewitt15@gmail.com>
This commit is contained in:
parent
07b02c2b5a
commit
f47ec9bb09
3
.gitignore
vendored
3
.gitignore
vendored
@ -65,3 +65,6 @@ typings/
|
|||||||
|
|
||||||
# next.js build output
|
# next.js build output
|
||||||
.next
|
.next
|
||||||
|
|
||||||
|
# auto generated barge yaml
|
||||||
|
subgraph.barge.yaml
|
@ -133,6 +133,7 @@ export ADDRESS_FILE="${HOME}/.ocean/ocean-contracts/artifacts/address.json"
|
|||||||
|
|
||||||
4. Generate the subgraph
|
4. Generate the subgraph
|
||||||
```bash
|
```bash
|
||||||
|
npm run codegen
|
||||||
npm run bargesetup
|
npm run bargesetup
|
||||||
```
|
```
|
||||||
|
|
||||||
|
17468
abis/Dispenser.json
Normal file
17468
abis/Dispenser.json
Normal file
File diff suppressed because one or more lines are too long
82
package-lock.json
generated
82
package-lock.json
generated
@ -399,17 +399,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@oceanprotocol/contracts": {
|
"@oceanprotocol/contracts": {
|
||||||
"version": "0.5.16",
|
"version": "0.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.16.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.6.2.tgz",
|
||||||
"integrity": "sha512-p7aFIUT8RVoMzdPP7ML8G08BnQ09syywKjOT16hqJm0GmofunEuVffUXbryG4EkQ+qRbf/zeoxSmesi79kQXlA=="
|
"integrity": "sha512-J6amHsmVbdc2rAwbUYOaY7inLV13GxPIiqbsLF78nmdIvhhGDhT2LYMyfQtxkMwQzYDP6EzD4albCgOXlWM15g=="
|
||||||
},
|
},
|
||||||
"@oceanprotocol/lib": {
|
"@oceanprotocol/lib": {
|
||||||
"version": "0.14.8",
|
"version": "0.14.9",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.14.8.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.14.9.tgz",
|
||||||
"integrity": "sha512-eqab5iEgowyIM/LcDDs6xhZo/KToOmVw0betjXLG0+g70zS8R6XL2RHzCpFyutSdf/cH0w/ltPUfR8ZBElIyhQ==",
|
"integrity": "sha512-PUNbsryrm4614CbvalP2CZS9LZjvWfqopTdb91Rz4vLbnqinioELSFXNq+hiSkyuFqAy0szG0wueBcW8mwFbSg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ethereum-navigator/navigator": "^0.5.2",
|
"@ethereum-navigator/navigator": "^0.5.2",
|
||||||
"@oceanprotocol/contracts": "0.5.16",
|
"@oceanprotocol/contracts": "^0.6.2",
|
||||||
"@types/crypto-js": "^4.0.1",
|
"@types/crypto-js": "^4.0.1",
|
||||||
"cross-fetch": "^3.1.2",
|
"cross-fetch": "^3.1.2",
|
||||||
"crypto-js": "^4.0.0",
|
"crypto-js": "^4.0.0",
|
||||||
@ -5163,9 +5163,9 @@
|
|||||||
"integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg=="
|
"integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg=="
|
||||||
},
|
},
|
||||||
"is-bigint": {
|
"is-bigint": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
|
||||||
"integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg=="
|
"integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA=="
|
||||||
},
|
},
|
||||||
"is-binary-path": {
|
"is-binary-path": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
@ -5182,11 +5182,32 @@
|
|||||||
"integrity": "sha1-o9fZb+HD/wZex84nwsIea6ksGDI="
|
"integrity": "sha1-o9fZb+HD/wZex84nwsIea6ksGDI="
|
||||||
},
|
},
|
||||||
"is-boolean-object": {
|
"is-boolean-object": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
|
||||||
"integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
|
"integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"call-bind": "^1.0.0"
|
"call-bind": "^1.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"get-intrinsic": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"has": "^1.0.3",
|
||||||
|
"has-symbols": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"is-buffer": {
|
"is-buffer": {
|
||||||
@ -5252,9 +5273,9 @@
|
|||||||
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
|
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
|
||||||
},
|
},
|
||||||
"is-generator-function": {
|
"is-generator-function": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz",
|
||||||
"integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ=="
|
"integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A=="
|
||||||
},
|
},
|
||||||
"is-glob": {
|
"is-glob": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
@ -5413,9 +5434,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-number-object": {
|
"is-number-object": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
|
||||||
"integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw=="
|
"integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw=="
|
||||||
},
|
},
|
||||||
"is-obj": {
|
"is-obj": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -5566,12 +5587,19 @@
|
|||||||
"integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
|
"integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
|
||||||
},
|
},
|
||||||
"is-regex": {
|
"is-regex": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
|
||||||
"integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==",
|
"integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"call-bind": "^1.0.2",
|
"call-bind": "^1.0.2",
|
||||||
"has-symbols": "^1.0.1"
|
"has-symbols": "^1.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"string.prototype.trimend": {
|
"string.prototype.trimend": {
|
||||||
@ -9818,9 +9846,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"utf-8-validate": {
|
"utf-8-validate": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz",
|
||||||
"integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==",
|
"integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-gyp-build": "^4.2.0"
|
"node-gyp-build": "^4.2.0"
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"typescript": "^4.2.4"
|
"typescript": "^4.2.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oceanprotocol/lib": "^0.14.8",
|
"@oceanprotocol/lib": "^0.14.9",
|
||||||
"cross-fetch": "^3.1.4"
|
"cross-fetch": "^3.1.4"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
368
schema.graphql
368
schema.graphql
@ -1,239 +1,255 @@
|
|||||||
type PoolFactory @entity {
|
type PoolFactory @entity {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
|
||||||
totalValueLocked: BigDecimal # total value from all pools expressed in OCEAN
|
totalValueLocked: BigDecimal # total value from all pools expressed in OCEAN
|
||||||
|
totalOceanLiquidity: BigDecimal! # Total of OCEAN liquidity from all pools
|
||||||
totalOceanLiquidity: BigDecimal! # Total of OCEAN liquidity from all pools
|
totalSwapVolume: BigDecimal! # All the swap volume in Ocean
|
||||||
totalSwapVolume: BigDecimal! # All the swap volume in Ocean
|
totalSwapFee: BigDecimal! # All the swap fee in Ocean
|
||||||
totalSwapFee: BigDecimal! # All the swap fee in Ocean
|
poolCount: Int! # Number of pools
|
||||||
|
finalizedPoolCount: Int! # Number of finalized pools
|
||||||
poolCount: Int! # Number of pools
|
pools: [Pool!] @derivedFrom(field: "factoryID")
|
||||||
finalizedPoolCount: Int! # Number of finalized pools
|
|
||||||
|
|
||||||
pools: [Pool!] @derivedFrom(field: "factoryID")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pool @entity {
|
type Pool @entity {
|
||||||
id: ID! # Pool address
|
id: ID! # Pool address
|
||||||
factoryID: PoolFactory!
|
factoryID: PoolFactory!
|
||||||
controller: Bytes! # Controller address
|
controller: Bytes! # Controller address
|
||||||
publicSwap: Boolean! # isPublicSwap
|
publicSwap: Boolean! # isPublicSwap
|
||||||
finalized: Boolean! # isFinalized
|
finalized: Boolean! # isFinalized
|
||||||
symbol: String # Pool token symbol
|
symbol: String # Pool token symbol
|
||||||
name: String # Pool token name
|
name: String # Pool token name
|
||||||
cap: BigInt # Maximum supply if any
|
cap: BigInt # Maximum supply if any
|
||||||
active: Boolean! # isActive
|
active: Boolean! # isActive
|
||||||
swapFee: BigDecimal! # Swap Fees
|
swapFee: BigDecimal! # Swap Fees
|
||||||
|
totalWeight: BigDecimal!
|
||||||
|
totalShares: BigDecimal! # Total pool token shares
|
||||||
|
totalSwapVolume: BigDecimal! # Total swap volume in OCEAN
|
||||||
|
totalSwapFee: BigDecimal! # Total swap fee in OCEAN
|
||||||
|
valueLocked: BigDecimal! # value locked in pool expressed in OCEAN (captures both Ocean and Datatoken)
|
||||||
|
datatokenReserve: BigDecimal! # Total pool reserve of Datatoken
|
||||||
|
oceanReserve: BigDecimal! # Total pool reserve of OCEAN
|
||||||
|
spotPrice: BigDecimal!
|
||||||
|
consumePrice: BigDecimal!
|
||||||
|
|
||||||
totalWeight: BigDecimal!
|
tokenCount: BigInt! # Number of tokens in the pool
|
||||||
totalShares: BigDecimal! # Total pool token shares
|
holderCount: BigInt! # Number of addresses holding a positive balance of pool shares
|
||||||
totalSwapVolume: BigDecimal! # Total swap volume in OCEAN
|
joinCount: BigInt! # liquidity has been added
|
||||||
totalSwapFee: BigDecimal! # Total swap fee in OCEAN
|
exitCount: BigInt! # liquidity has been removed
|
||||||
|
swapCount: BigInt!
|
||||||
valueLocked: BigDecimal! # value locked in pool expressed in OCEAN (captures both Ocean and Datatoken)
|
transactionCount: BigInt! # Number of transactions in this pool involving liquidity changes
|
||||||
datatokenReserve: BigDecimal! # Total pool reserve of Datatoken
|
datatokenAddress: String!
|
||||||
oceanReserve: BigDecimal! # Total pool reserve of OCEAN
|
createTime: Int! # Block time pool was created
|
||||||
spotPrice: BigDecimal!
|
tx: Bytes # Pool creation transaction id
|
||||||
consumePrice: BigDecimal!
|
tokens: [PoolToken!] @derivedFrom(field: "poolId")
|
||||||
|
shares: [PoolShare!] @derivedFrom(field: "poolId")
|
||||||
tokenCount: BigInt! # Number of tokens in the pool
|
transactions: [PoolTransaction!] @derivedFrom(field: "poolAddress")
|
||||||
holderCount: BigInt! # Number of addresses holding a positive balance of pool shares
|
transactionsTokenValues: [PoolTransactionTokenValues!]
|
||||||
joinCount: BigInt! # liquidity has been added
|
@derivedFrom(field: "poolAddress")
|
||||||
exitCount: BigInt! # liquidity has been removed
|
|
||||||
swapCount: BigInt!
|
|
||||||
transactionCount: BigInt! # Number of transactions in this pool involving liquidity changes
|
|
||||||
|
|
||||||
datatokenAddress: String!
|
|
||||||
createTime: Int! # Block time pool was created
|
|
||||||
tx: Bytes # Pool creation transaction id
|
|
||||||
|
|
||||||
tokens: [PoolToken!] @derivedFrom(field: "poolId")
|
|
||||||
shares: [PoolShare!] @derivedFrom(field: "poolId")
|
|
||||||
transactions: [PoolTransaction!] @derivedFrom(field: "poolAddress")
|
|
||||||
transactionsTokenValues: [PoolTransactionTokenValues!] @derivedFrom(field: "poolAddress")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PoolToken @entity {
|
type PoolToken @entity {
|
||||||
id: ID! # poolId + token address
|
id: ID! # poolId + token address
|
||||||
poolId: Pool!
|
poolId: Pool!
|
||||||
tokenId: Datatoken
|
tokenId: Datatoken
|
||||||
tokenAddress: String
|
tokenAddress: String
|
||||||
balance: BigDecimal!
|
balance: BigDecimal!
|
||||||
denormWeight: BigDecimal!
|
denormWeight: BigDecimal!
|
||||||
}
|
}
|
||||||
|
|
||||||
type PoolShare @entity {
|
type PoolShare @entity {
|
||||||
id: ID! # poolId + userAddress
|
id: ID! # poolId + userAddress
|
||||||
userAddress: User!
|
userAddress: User!
|
||||||
poolId: Pool!
|
poolId: Pool!
|
||||||
balance: BigDecimal!
|
balance: BigDecimal!
|
||||||
}
|
}
|
||||||
|
|
||||||
type PoolTransactionTokenValues @entity {
|
type PoolTransactionTokenValues @entity {
|
||||||
id: ID! # pool tx + tokenAddress
|
id: ID! # pool tx + tokenAddress
|
||||||
txId: PoolTransaction!
|
txId: PoolTransaction!
|
||||||
poolToken: PoolToken!
|
poolToken: PoolToken!
|
||||||
poolAddress: Pool!
|
poolAddress: Pool!
|
||||||
userAddress: User!
|
userAddress: User!
|
||||||
tokenAddress: String!
|
tokenAddress: String!
|
||||||
|
|
||||||
value: BigDecimal!
|
value: BigDecimal!
|
||||||
tokenReserve: BigDecimal!
|
tokenReserve: BigDecimal!
|
||||||
feeValue: BigDecimal! # Swap fee value in OCEAN
|
feeValue: BigDecimal! # Swap fee value in OCEAN
|
||||||
type: String!
|
type: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type PoolTransaction @entity {
|
type PoolTransaction @entity {
|
||||||
id: ID! # pool tx
|
id: ID! # pool tx
|
||||||
poolAddress: Pool
|
poolAddress: Pool
|
||||||
userAddress: User # User address that initiates the swap
|
userAddress: User # User address that initiates the swap
|
||||||
poolAddressStr: String!
|
poolAddressStr: String!
|
||||||
userAddressStr: String!
|
userAddressStr: String!
|
||||||
|
|
||||||
sharesTransferAmount: BigDecimal! #
|
sharesTransferAmount: BigDecimal! #
|
||||||
sharesBalance: BigDecimal!
|
sharesBalance: BigDecimal!
|
||||||
|
|
||||||
spotPrice: BigDecimal!
|
spotPrice: BigDecimal!
|
||||||
consumePrice: BigDecimal!
|
consumePrice: BigDecimal!
|
||||||
tx: Bytes!
|
tx: Bytes!
|
||||||
event: String
|
event: String
|
||||||
block: Int!
|
block: Int!
|
||||||
timestamp: Int!
|
timestamp: Int!
|
||||||
gasUsed: BigDecimal!
|
gasUsed: BigDecimal!
|
||||||
gasPrice: BigDecimal!
|
gasPrice: BigDecimal!
|
||||||
|
|
||||||
oceanReserve: BigDecimal!
|
oceanReserve: BigDecimal!
|
||||||
datatokenReserve: BigDecimal!
|
datatokenReserve: BigDecimal!
|
||||||
|
|
||||||
tokens: [PoolTransactionTokenValues!] @derivedFrom(field: "txId")
|
tokens: [PoolTransactionTokenValues!] @derivedFrom(field: "txId")
|
||||||
}
|
}
|
||||||
|
|
||||||
type DatatokenFactory @entity {
|
type DatatokenFactory @entity {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
|
||||||
tokenCount: Int! # Number of datatokens
|
tokenCount: Int! # Number of datatokens
|
||||||
|
datatokens: [Datatoken!] @derivedFrom(field: "factoryID")
|
||||||
datatokens: [Datatoken!] @derivedFrom(field: "factoryID")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Datatoken @entity {
|
type Datatoken @entity {
|
||||||
id: ID! # token address
|
id: ID! # token address
|
||||||
factoryID: DatatokenFactory!
|
factoryID: DatatokenFactory!
|
||||||
|
|
||||||
symbol: String
|
symbol: String
|
||||||
name: String
|
name: String
|
||||||
decimals: Int!
|
decimals: Int!
|
||||||
address: String!
|
address: String!
|
||||||
cap: BigDecimal!
|
cap: BigDecimal!
|
||||||
supply: BigDecimal!
|
supply: BigDecimal!
|
||||||
minter: User!
|
minter: User!
|
||||||
publisher: String!
|
publisher: String!
|
||||||
|
|
||||||
holderCount: BigInt! # Number of addresses holding a balance of datatoken
|
holderCount: BigInt! # Number of addresses holding a balance of datatoken
|
||||||
orderCount: BigInt! # Number of orders executed for this dataset
|
orderCount: BigInt! # Number of orders executed for this dataset
|
||||||
metadataUpdateCount: BigInt!
|
metadataUpdateCount: BigInt!
|
||||||
|
|
||||||
createTime: Int! # Block time datatoken was created
|
createTime: Int! # Block time datatoken was created
|
||||||
tx: Bytes # Datatoken creation transaction id
|
tx: Bytes # Datatoken creation transaction id
|
||||||
|
balances: [TokenBalance!] @derivedFrom(field: "datatokenId")
|
||||||
balances: [TokenBalance!] @derivedFrom(field: "datatokenId")
|
orders: [TokenOrder!] @derivedFrom(field: "datatokenId")
|
||||||
orders: [TokenOrder!] @derivedFrom(field: "datatokenId")
|
updates: [MetadataUpdate!] @derivedFrom(field: "datatokenId") # list of MetadataUpdate objects
|
||||||
updates: [MetadataUpdate!] @derivedFrom(field: "datatokenId") # list of MetadataUpdate objects
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetadataUpdate @entity {
|
type MetadataUpdate @entity {
|
||||||
id: ID! # update tx + datatokenAddress
|
id: ID! # update tx + datatokenAddress
|
||||||
datatokenId: Datatoken!
|
datatokenId: Datatoken!
|
||||||
|
|
||||||
datatokenAddress: String!
|
datatokenAddress: String!
|
||||||
userAddress: String!
|
userAddress: String!
|
||||||
|
|
||||||
block: Int!
|
block: Int!
|
||||||
timestamp: Int!
|
timestamp: Int!
|
||||||
tx: Bytes!
|
tx: Bytes!
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenOrder @entity {
|
type TokenOrder @entity {
|
||||||
id: ID! # datatokenId + userAddress + tx
|
id: ID! # datatokenId + userAddress + tx
|
||||||
|
datatokenId: Datatoken!
|
||||||
|
|
||||||
datatokenId: Datatoken!
|
consumer: User!
|
||||||
|
payer: User!
|
||||||
|
amount: BigDecimal!
|
||||||
|
serviceId: Int!
|
||||||
|
marketFeeCollector: User
|
||||||
|
marketFee: BigDecimal!
|
||||||
|
|
||||||
consumer: User!
|
timestamp: Int!
|
||||||
payer: User!
|
tx: Bytes
|
||||||
amount: BigDecimal!
|
block: Int!
|
||||||
serviceId: Int!
|
|
||||||
marketFeeCollector: User
|
|
||||||
marketFee: BigDecimal!
|
|
||||||
|
|
||||||
timestamp: Int!
|
|
||||||
tx: Bytes
|
|
||||||
block: Int!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenBalance @entity {
|
type TokenBalance @entity {
|
||||||
id: ID! # datatokenId + userAddress
|
id: ID! # datatokenId + userAddress
|
||||||
userAddress: User!
|
userAddress: User!
|
||||||
datatokenId: Datatoken!
|
datatokenId: Datatoken!
|
||||||
balance: BigDecimal!
|
balance: BigDecimal!
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenTransaction @entity {
|
type TokenTransaction @entity {
|
||||||
id: ID! # Log ID
|
id: ID! # Log ID
|
||||||
|
event: String
|
||||||
|
datatokenAddress: Datatoken
|
||||||
|
userAddress: User
|
||||||
|
|
||||||
event: String
|
block: Int!
|
||||||
datatokenAddress: Datatoken
|
gasUsed: BigDecimal!
|
||||||
userAddress: User
|
gasPrice: BigDecimal!
|
||||||
|
timestamp: Int!
|
||||||
block: Int!
|
tx: Bytes!
|
||||||
gasUsed: BigDecimal!
|
|
||||||
gasPrice: BigDecimal!
|
|
||||||
timestamp: Int!
|
|
||||||
tx: Bytes!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type User @entity {
|
type User @entity {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
|
||||||
sharesOwned: [PoolShare!] @derivedFrom(field: "userAddress")
|
sharesOwned: [PoolShare!] @derivedFrom(field: "userAddress")
|
||||||
tokenBalancesOwned: [TokenBalance!] @derivedFrom(field: "userAddress")
|
tokenBalancesOwned: [TokenBalance!] @derivedFrom(field: "userAddress")
|
||||||
tokensOwned: [Datatoken!] @derivedFrom(field: "minter")
|
tokensOwned: [Datatoken!] @derivedFrom(field: "minter")
|
||||||
poolTransactions: [PoolTransaction!] @derivedFrom(field: "userAddress")
|
poolTransactions: [PoolTransaction!] @derivedFrom(field: "userAddress")
|
||||||
poolTransactionsTokenValues: [PoolTransactionTokenValues!] @derivedFrom(field: "userAddress")
|
poolTransactionsTokenValues: [PoolTransactionTokenValues!]
|
||||||
tokenTransactions: [TokenTransaction!] @derivedFrom(field: "userAddress")
|
@derivedFrom(field: "userAddress")
|
||||||
orders: [TokenOrder!] @derivedFrom(field: "payer")
|
tokenTransactions: [TokenTransaction!] @derivedFrom(field: "userAddress")
|
||||||
freSwaps: [FixedRateExchangeSwap!] @derivedFrom(field: "by")
|
orders: [TokenOrder!] @derivedFrom(field: "payer")
|
||||||
|
freSwaps: [FixedRateExchangeSwap!] @derivedFrom(field: "by")
|
||||||
}
|
}
|
||||||
|
|
||||||
type FixedRateExchange @entity {
|
type FixedRateExchange @entity {
|
||||||
id: ID! # fixed rate exchange id
|
id: ID! # fixed rate exchange id
|
||||||
exchangeOwner: User!
|
exchangeOwner: User!
|
||||||
datatoken: Datatoken!
|
datatoken: Datatoken!
|
||||||
baseToken: String!
|
baseToken: String!
|
||||||
rate: BigDecimal!
|
rate: BigDecimal!
|
||||||
active: Boolean!
|
active: Boolean!
|
||||||
updates: [FixedRateExchangeUpdate!] @derivedFrom(field: "exchangeId")
|
updates: [FixedRateExchangeUpdate!] @derivedFrom(field: "exchangeId")
|
||||||
swaps: [FixedRateExchangeSwap!] @derivedFrom(field: "exchangeId")
|
swaps: [FixedRateExchangeSwap!] @derivedFrom(field: "exchangeId")
|
||||||
}
|
}
|
||||||
|
|
||||||
type FixedRateExchangeUpdate @entity {
|
type FixedRateExchangeUpdate @entity {
|
||||||
id: ID!
|
id: ID!
|
||||||
exchangeId: FixedRateExchange!
|
exchangeId: FixedRateExchange!
|
||||||
oldRate: BigDecimal!
|
oldRate: BigDecimal!
|
||||||
newRate: BigDecimal!
|
newRate: BigDecimal!
|
||||||
oldActive: Boolean!
|
oldActive: Boolean!
|
||||||
newActive: Boolean!
|
newActive: Boolean!
|
||||||
block: Int!
|
block: Int!
|
||||||
timestamp: Int!
|
timestamp: Int!
|
||||||
tx: Bytes!
|
tx: Bytes!
|
||||||
}
|
}
|
||||||
|
|
||||||
type FixedRateExchangeSwap @entity {
|
type FixedRateExchangeSwap @entity {
|
||||||
id: ID!
|
id: ID!
|
||||||
exchangeId: FixedRateExchange!
|
exchangeId: FixedRateExchange!
|
||||||
by: User!
|
by: User!
|
||||||
baseTokenAmount: BigDecimal!
|
baseTokenAmount: BigDecimal!
|
||||||
dataTokenAmount: BigDecimal!
|
dataTokenAmount: BigDecimal!
|
||||||
block: Int!
|
block: Int!
|
||||||
timestamp: Int!
|
timestamp: Int!
|
||||||
tx: Bytes!
|
tx: Bytes!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Dispenser @entity {
|
||||||
|
id: ID! # dispenser datatoken
|
||||||
|
active: Boolean!
|
||||||
|
owner: User!
|
||||||
|
minterApproved: Boolean!
|
||||||
|
isTrueMinter: Boolean!
|
||||||
|
maxTokens: BigDecimal!
|
||||||
|
maxBalance: BigDecimal!
|
||||||
|
balance: BigDecimal!
|
||||||
|
datatoken: Datatoken!
|
||||||
|
dispenses: [DispenserTransaction!] @derivedFrom(field: "dispenserId")
|
||||||
|
}
|
||||||
|
|
||||||
|
type DispenserTransaction @entity {
|
||||||
|
id: ID!
|
||||||
|
dispenserId: Dispenser!
|
||||||
|
datatoken: Datatoken!
|
||||||
|
user: User!
|
||||||
|
amount: BigDecimal!
|
||||||
|
block: Int!
|
||||||
|
timestamp: Int!
|
||||||
|
tx: Bytes!
|
||||||
|
type: String!
|
||||||
|
}
|
||||||
|
@ -12,7 +12,9 @@ async function replaceContractAddresses() {
|
|||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
FixedRateExchange,
|
FixedRateExchange,
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
Metadata
|
Metadata,
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
Dispenser
|
||||||
} = data.development
|
} = data.development
|
||||||
let subgraph = fs.readFileSync('subgraph.yaml', 'utf8')
|
let subgraph = fs.readFileSync('subgraph.yaml', 'utf8')
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@ -38,6 +40,11 @@ async function replaceContractAddresses() {
|
|||||||
/0x608d05214E42722B94a54cF6114d4840FCfF84e1/g,
|
/0x608d05214E42722B94a54cF6114d4840FCfF84e1/g,
|
||||||
FixedRateExchange
|
FixedRateExchange
|
||||||
)
|
)
|
||||||
|
// dispenser
|
||||||
|
subgraph = subgraph.replace(
|
||||||
|
/0xDEfD0018969cd2d4E648209F876ADe184815f038/g,
|
||||||
|
Dispenser
|
||||||
|
)
|
||||||
// network
|
// network
|
||||||
subgraph = subgraph.replace(/network: mainnet/g, 'network: barge')
|
subgraph = subgraph.replace(/network: mainnet/g, 'network: barge')
|
||||||
|
|
||||||
|
176
src/mappings/dispenser.ts
Normal file
176
src/mappings/dispenser.ts
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
import { Address, BigInt, ethereum, log } from '@graphprotocol/graph-ts'
|
||||||
|
import {
|
||||||
|
Activated,
|
||||||
|
Deactivated,
|
||||||
|
AcceptedMinter,
|
||||||
|
RemovedMinter,
|
||||||
|
TokensDispensed,
|
||||||
|
OwnerWithdrawed,
|
||||||
|
Dispenser as DispenserEntity
|
||||||
|
} from '../@types/Dispenser/Dispenser'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Dispenser,
|
||||||
|
DispenserTransaction,
|
||||||
|
User,
|
||||||
|
Datatoken
|
||||||
|
} from '../@types/schema'
|
||||||
|
|
||||||
|
import { tokenToDecimal, _debuglog } from '../helpers'
|
||||||
|
|
||||||
|
function _processDispenserUpdate(
|
||||||
|
event: ethereum.Event,
|
||||||
|
datatoken: string,
|
||||||
|
contractAddress: Address
|
||||||
|
): void {
|
||||||
|
_debuglog('Start processDispenserUpdate', null, [
|
||||||
|
datatoken,
|
||||||
|
contractAddress.toHexString()
|
||||||
|
])
|
||||||
|
const dt = Datatoken.load(datatoken)
|
||||||
|
if (!dt) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let dispenser = Dispenser.load(datatoken)
|
||||||
|
if (!dispenser) {
|
||||||
|
_debuglog('Creating new dispenser', null, null)
|
||||||
|
dispenser = new Dispenser(datatoken)
|
||||||
|
}
|
||||||
|
const dispenserEntity = DispenserEntity.bind(contractAddress)
|
||||||
|
_debuglog('Bound dispenser entity', null, null)
|
||||||
|
const dispenserStatus = dispenserEntity.try_status(
|
||||||
|
Address.fromString(datatoken)
|
||||||
|
)
|
||||||
|
_debuglog('Got status', null, null)
|
||||||
|
if (dispenserStatus.reverted) return
|
||||||
|
dispenser.active = dispenserStatus.value.value0
|
||||||
|
let owner = User.load(dispenserStatus.value.value1.toHexString())
|
||||||
|
if (!owner) {
|
||||||
|
owner = new User(dispenserStatus.value.value1.toHexString())
|
||||||
|
owner.save()
|
||||||
|
}
|
||||||
|
dispenser.owner = owner.id
|
||||||
|
dispenser.minterApproved = dispenserStatus.value.value2
|
||||||
|
dispenser.isTrueMinter = dispenserStatus.value.value3
|
||||||
|
dispenser.maxTokens = tokenToDecimal(
|
||||||
|
dispenserStatus.value.value4.toBigDecimal(),
|
||||||
|
18
|
||||||
|
)
|
||||||
|
dispenser.maxBalance = tokenToDecimal(
|
||||||
|
dispenserStatus.value.value5.toBigDecimal(),
|
||||||
|
18
|
||||||
|
)
|
||||||
|
dispenser.balance = tokenToDecimal(
|
||||||
|
dispenserStatus.value.value6.toBigDecimal(),
|
||||||
|
18
|
||||||
|
)
|
||||||
|
dispenser.datatoken = dt.id
|
||||||
|
dispenser.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleDispenserActivated(event: Activated): void {
|
||||||
|
_debuglog('Start handleDispenserActivated', event, [
|
||||||
|
event.params.datatokenAddress.toHexString()
|
||||||
|
])
|
||||||
|
_processDispenserUpdate(
|
||||||
|
event,
|
||||||
|
event.params.datatokenAddress.toHexString(),
|
||||||
|
event.address
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleDispenserDeactivated(event: Deactivated): void {
|
||||||
|
_processDispenserUpdate(
|
||||||
|
event,
|
||||||
|
event.params.datatokenAddress.toHexString(),
|
||||||
|
event.address
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export function handleDispenserAcceptedMinter(event: AcceptedMinter): void {
|
||||||
|
_processDispenserUpdate(
|
||||||
|
event,
|
||||||
|
event.params.datatokenAddress.toHexString(),
|
||||||
|
event.address
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export function handleDispenserRemovedMinter(event: RemovedMinter): void {
|
||||||
|
_processDispenserUpdate(
|
||||||
|
event,
|
||||||
|
event.params.datatokenAddress.toHexString(),
|
||||||
|
event.address
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleDispenserTokensDispensed(event: TokensDispensed): void {
|
||||||
|
_processDispenserUpdate(
|
||||||
|
event,
|
||||||
|
event.params.datatokenAddress.toHexString(),
|
||||||
|
event.address
|
||||||
|
)
|
||||||
|
const dt = Datatoken.load(event.params.datatokenAddress.toHexString())
|
||||||
|
if (!dt) {
|
||||||
|
log.warning('Tokens dispensed, but no datatoken ? ', [
|
||||||
|
event.params.datatokenAddress.toHexString()
|
||||||
|
])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const tx = event.transaction.hash
|
||||||
|
const id = tx
|
||||||
|
.toHexString()
|
||||||
|
.concat('-')
|
||||||
|
.concat(event.params.datatokenAddress.toHexString())
|
||||||
|
log.info('Created dispenser in handleDispenserTokensDispensed with id {}', [
|
||||||
|
id
|
||||||
|
])
|
||||||
|
const dispensers = new DispenserTransaction(id)
|
||||||
|
dispensers.dispenserId = event.params.datatokenAddress.toHexString()
|
||||||
|
dispensers.datatoken = event.params.datatokenAddress.toHexString()
|
||||||
|
dispensers.user = event.params.userAddress.toHexString()
|
||||||
|
dispensers.amount = tokenToDecimal(
|
||||||
|
event.params.amount.toBigDecimal(),
|
||||||
|
BigInt.fromI32(18).toI32()
|
||||||
|
)
|
||||||
|
dispensers.block = event.block.number.toI32()
|
||||||
|
dispensers.timestamp = event.block.timestamp.toI32()
|
||||||
|
dispensers.tx = tx
|
||||||
|
dispensers.type = 'dispense'
|
||||||
|
dispensers.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handleDispenserOwnerWithdrawed(event: OwnerWithdrawed): void {
|
||||||
|
_processDispenserUpdate(
|
||||||
|
event,
|
||||||
|
event.params.datatoken.toHexString(),
|
||||||
|
event.address
|
||||||
|
)
|
||||||
|
const dt = Datatoken.load(event.params.datatoken.toHexString())
|
||||||
|
if (!dt) {
|
||||||
|
log.warning('Tokens dispensed, but no datatoken ? ', [
|
||||||
|
event.params.datatoken.toHexString()
|
||||||
|
])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const tx = event.transaction.hash
|
||||||
|
const id = tx
|
||||||
|
.toHexString()
|
||||||
|
.concat('-')
|
||||||
|
.concat(event.params.datatoken.toHexString())
|
||||||
|
log.info('Created dispenser in handleDispenserOwnerWithdrawed with id {} ', [
|
||||||
|
id
|
||||||
|
])
|
||||||
|
const dispensers = new DispenserTransaction(id)
|
||||||
|
dispensers.dispenserId = event.params.datatoken.toHexString()
|
||||||
|
dispensers.datatoken = event.params.datatoken.toHexString()
|
||||||
|
dispensers.user = event.params.owner.toHexString()
|
||||||
|
dispensers.amount = tokenToDecimal(
|
||||||
|
event.params.amount.toBigDecimal(),
|
||||||
|
BigInt.fromI32(18).toI32()
|
||||||
|
)
|
||||||
|
dispensers.block = event.block.number.toI32()
|
||||||
|
dispensers.timestamp = event.block.timestamp.toI32()
|
||||||
|
dispensers.tx = tx
|
||||||
|
dispensers.type = 'withdraw'
|
||||||
|
dispensers.save()
|
||||||
|
}
|
@ -94,6 +94,36 @@ dataSources:
|
|||||||
handler: handleExchangeRateChanged
|
handler: handleExchangeRateChanged
|
||||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||||
handler: handleSwapped
|
handler: handleSwapped
|
||||||
|
- kind: ethereum/contract
|
||||||
|
name: Dispenser
|
||||||
|
network: moonbeamalpha
|
||||||
|
source:
|
||||||
|
address: '0x042D709b72B437d7d387F2679bD4ac060e561c9f'
|
||||||
|
abi: Dispenser
|
||||||
|
startBlock: 260710
|
||||||
|
mapping:
|
||||||
|
kind: ethereum/events
|
||||||
|
apiVersion: 0.0.4
|
||||||
|
language: wasm/assemblyscript
|
||||||
|
file: ./src/mappings/dispenser.ts
|
||||||
|
entities:
|
||||||
|
- Dispenser
|
||||||
|
abis:
|
||||||
|
- name: Dispenser
|
||||||
|
file: ./abis/Dispenser.json
|
||||||
|
eventHandlers:
|
||||||
|
- event: Activated(indexed address)
|
||||||
|
handler: handleDispenserActivated
|
||||||
|
- event: Deactivated(indexed address)
|
||||||
|
handler: handleDispenserDeactivated
|
||||||
|
- event: AcceptedMinter(indexed address)
|
||||||
|
handler: handleDispenserAcceptedMinter
|
||||||
|
- event: RemovedMinter(indexed address)
|
||||||
|
handler: handleDispenserRemovedMinter
|
||||||
|
- event: TokensDispensed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserTokensDispensed
|
||||||
|
- event: OwnerWithdrawed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserOwnerWithdrawed
|
||||||
templates:
|
templates:
|
||||||
- kind: ethereum/contract
|
- kind: ethereum/contract
|
||||||
name: Pool
|
name: Pool
|
||||||
|
@ -94,6 +94,36 @@ dataSources:
|
|||||||
handler: handleExchangeRateChanged
|
handler: handleExchangeRateChanged
|
||||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||||
handler: handleSwapped
|
handler: handleSwapped
|
||||||
|
- kind: ethereum/contract
|
||||||
|
name: Dispenser
|
||||||
|
network: polygon
|
||||||
|
source:
|
||||||
|
address: '0x30E4CC2C7A9c6aA2b2Ce93586E3Df24a3A00bcDD'
|
||||||
|
abi: Dispenser
|
||||||
|
startBlock: 14275634
|
||||||
|
mapping:
|
||||||
|
kind: ethereum/events
|
||||||
|
apiVersion: 0.0.4
|
||||||
|
language: wasm/assemblyscript
|
||||||
|
file: ./src/mappings/dispenser.ts
|
||||||
|
entities:
|
||||||
|
- Dispenser
|
||||||
|
abis:
|
||||||
|
- name: Dispenser
|
||||||
|
file: ./abis/Dispenser.json
|
||||||
|
eventHandlers:
|
||||||
|
- event: Activated(indexed address)
|
||||||
|
handler: handleDispenserActivated
|
||||||
|
- event: Deactivated(indexed address)
|
||||||
|
handler: handleDispenserDeactivated
|
||||||
|
- event: AcceptedMinter(indexed address)
|
||||||
|
handler: handleDispenserAcceptedMinter
|
||||||
|
- event: RemovedMinter(indexed address)
|
||||||
|
handler: handleDispenserRemovedMinter
|
||||||
|
- event: TokensDispensed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserTokensDispensed
|
||||||
|
- event: OwnerWithdrawed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserOwnerWithdrawed
|
||||||
templates:
|
templates:
|
||||||
- kind: ethereum/contract
|
- kind: ethereum/contract
|
||||||
name: Pool
|
name: Pool
|
||||||
|
@ -94,6 +94,36 @@ dataSources:
|
|||||||
handler: handleExchangeRateChanged
|
handler: handleExchangeRateChanged
|
||||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||||
handler: handleSwapped
|
handler: handleSwapped
|
||||||
|
- kind: ethereum/contract
|
||||||
|
name: Dispenser
|
||||||
|
network: rinkeby
|
||||||
|
source:
|
||||||
|
address: '0x623744Cd25Ed553d3b4722667697F926cf99658B'
|
||||||
|
abi: Dispenser
|
||||||
|
startBlock: 8554110
|
||||||
|
mapping:
|
||||||
|
kind: ethereum/events
|
||||||
|
apiVersion: 0.0.4
|
||||||
|
language: wasm/assemblyscript
|
||||||
|
file: ./src/mappings/dispenser.ts
|
||||||
|
entities:
|
||||||
|
- Dispenser
|
||||||
|
abis:
|
||||||
|
- name: Dispenser
|
||||||
|
file: ./abis/Dispenser.json
|
||||||
|
eventHandlers:
|
||||||
|
- event: Activated(indexed address)
|
||||||
|
handler: handleDispenserActivated
|
||||||
|
- event: Deactivated(indexed address)
|
||||||
|
handler: handleDispenserDeactivated
|
||||||
|
- event: AcceptedMinter(indexed address)
|
||||||
|
handler: handleDispenserAcceptedMinter
|
||||||
|
- event: RemovedMinter(indexed address)
|
||||||
|
handler: handleDispenserRemovedMinter
|
||||||
|
- event: TokensDispensed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserTokensDispensed
|
||||||
|
- event: OwnerWithdrawed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserOwnerWithdrawed
|
||||||
templates:
|
templates:
|
||||||
- kind: ethereum/contract
|
- kind: ethereum/contract
|
||||||
name: Pool
|
name: Pool
|
||||||
|
@ -94,6 +94,36 @@ dataSources:
|
|||||||
handler: handleExchangeRateChanged
|
handler: handleExchangeRateChanged
|
||||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||||
handler: handleSwapped
|
handler: handleSwapped
|
||||||
|
- kind: ethereum/contract
|
||||||
|
name: Dispenser
|
||||||
|
network: ropsten
|
||||||
|
source:
|
||||||
|
address: '0xc37F8341Ac6e4a94538302bCd4d49Cf0852D30C0'
|
||||||
|
abi: Dispenser
|
||||||
|
startBlock: 10201082
|
||||||
|
mapping:
|
||||||
|
kind: ethereum/events
|
||||||
|
apiVersion: 0.0.4
|
||||||
|
language: wasm/assemblyscript
|
||||||
|
file: ./src/mappings/dispenser.ts
|
||||||
|
entities:
|
||||||
|
- Dispenser
|
||||||
|
abis:
|
||||||
|
- name: Dispenser
|
||||||
|
file: ./abis/Dispenser.json
|
||||||
|
eventHandlers:
|
||||||
|
- event: Activated(indexed address)
|
||||||
|
handler: handleDispenserActivated
|
||||||
|
- event: Deactivated(indexed address)
|
||||||
|
handler: handleDispenserDeactivated
|
||||||
|
- event: AcceptedMinter(indexed address)
|
||||||
|
handler: handleDispenserAcceptedMinter
|
||||||
|
- event: RemovedMinter(indexed address)
|
||||||
|
handler: handleDispenserRemovedMinter
|
||||||
|
- event: TokensDispensed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserTokensDispensed
|
||||||
|
- event: OwnerWithdrawed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserOwnerWithdrawed
|
||||||
templates:
|
templates:
|
||||||
- kind: ethereum/contract
|
- kind: ethereum/contract
|
||||||
name: Pool
|
name: Pool
|
||||||
|
@ -94,6 +94,36 @@ dataSources:
|
|||||||
handler: handleExchangeRateChanged
|
handler: handleExchangeRateChanged
|
||||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||||
handler: handleSwapped
|
handler: handleSwapped
|
||||||
|
- kind: ethereum/contract
|
||||||
|
name: Dispenser
|
||||||
|
network: mainnet
|
||||||
|
source:
|
||||||
|
address: '0xDEfD0018969cd2d4E648209F876ADe184815f038'
|
||||||
|
abi: Dispenser
|
||||||
|
startBlock: 12398958
|
||||||
|
mapping:
|
||||||
|
kind: ethereum/events
|
||||||
|
apiVersion: 0.0.4
|
||||||
|
language: wasm/assemblyscript
|
||||||
|
file: ./src/mappings/dispenser.ts
|
||||||
|
entities:
|
||||||
|
- Dispenser
|
||||||
|
abis:
|
||||||
|
- name: Dispenser
|
||||||
|
file: ./abis/Dispenser.json
|
||||||
|
eventHandlers:
|
||||||
|
- event: Activated(indexed address)
|
||||||
|
handler: handleDispenserActivated
|
||||||
|
- event: Deactivated(indexed address)
|
||||||
|
handler: handleDispenserDeactivated
|
||||||
|
- event: AcceptedMinter(indexed address)
|
||||||
|
handler: handleDispenserAcceptedMinter
|
||||||
|
- event: RemovedMinter(indexed address)
|
||||||
|
handler: handleDispenserRemovedMinter
|
||||||
|
- event: TokensDispensed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserTokensDispensed
|
||||||
|
- event: OwnerWithdrawed(indexed address,indexed address,uint256)
|
||||||
|
handler: handleDispenserOwnerWithdrawed
|
||||||
templates:
|
templates:
|
||||||
- kind: ethereum/contract
|
- kind: ethereum/contract
|
||||||
name: Pool
|
name: Pool
|
||||||
|
235
test/integration/Dispenser.test.ts
Normal file
235
test/integration/Dispenser.test.ts
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/* eslint-disable prefer-destructuring */
|
||||||
|
import { assert, use } from 'chai'
|
||||||
|
import spies from 'chai-spies'
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import { Ocean, ConfigHelper, Account } from '@oceanprotocol/lib'
|
||||||
|
const fetch = require('cross-fetch')
|
||||||
|
const web3 = new Web3('http://127.0.0.1:8545')
|
||||||
|
const subgraphUrl =
|
||||||
|
'http://localhost:9000/subgraphs/name/oceanprotocol/ocean-subgraph'
|
||||||
|
function sleep(ms: number) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDispenserStatusFromGraph(datatoken: string) {
|
||||||
|
const id = datatoken.toLowerCase()
|
||||||
|
const query = {
|
||||||
|
query: `query {
|
||||||
|
dispenser(id:"${id}"){active,owner{id},minterApproved,isTrueMinter,maxTokens,maxBalance,balance,datatoken{id}}}`
|
||||||
|
}
|
||||||
|
const response = await fetch(subgraphUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(query)
|
||||||
|
})
|
||||||
|
const result = await response.json()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
use(spies)
|
||||||
|
|
||||||
|
describe('Dispenser test flow', () => {
|
||||||
|
let alice: Account
|
||||||
|
let bob: Account
|
||||||
|
let ocean: Ocean
|
||||||
|
let tokenAddress
|
||||||
|
let tokenAddress2
|
||||||
|
let tokenAddress3
|
||||||
|
const tokenAmount = '1000'
|
||||||
|
it('Initialize Ocean Library', async () => {
|
||||||
|
const config = new ConfigHelper().getConfig('development')
|
||||||
|
config.web3Provider = web3
|
||||||
|
ocean = await Ocean.getInstance(config)
|
||||||
|
alice = (await ocean.accounts.list())[0]
|
||||||
|
bob = (await ocean.accounts.list())[1]
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should create some datatokens', async () => {
|
||||||
|
tokenAddress = await ocean.datatokens.create(
|
||||||
|
'',
|
||||||
|
alice.getId(),
|
||||||
|
'1000000000000000',
|
||||||
|
'AliceDT',
|
||||||
|
'DTA'
|
||||||
|
)
|
||||||
|
assert(tokenAddress !== null)
|
||||||
|
tokenAddress2 = await ocean.datatokens.create(
|
||||||
|
'',
|
||||||
|
alice.getId(),
|
||||||
|
'1000000000000000',
|
||||||
|
'AliceDT2',
|
||||||
|
'DTA2'
|
||||||
|
)
|
||||||
|
assert(tokenAddress2 !== null)
|
||||||
|
tokenAddress3 = await ocean.datatokens.create(
|
||||||
|
'',
|
||||||
|
alice.getId(),
|
||||||
|
'1000000000000000',
|
||||||
|
'AliceDT3',
|
||||||
|
'DTA3'
|
||||||
|
)
|
||||||
|
assert(tokenAddress3 !== null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Alice mints 1000 tokens', async () => {
|
||||||
|
const txid = await ocean.datatokens.mint(
|
||||||
|
tokenAddress,
|
||||||
|
alice.getId(),
|
||||||
|
tokenAmount
|
||||||
|
)
|
||||||
|
assert(txid !== null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Alice creates a dispenser', async () => {
|
||||||
|
const tx = await ocean.OceanDispenser.activate(
|
||||||
|
tokenAddress,
|
||||||
|
'1',
|
||||||
|
'1',
|
||||||
|
alice.getId()
|
||||||
|
)
|
||||||
|
assert(tx, 'Cannot activate dispenser')
|
||||||
|
await sleep(3000) // let graph ingest our transaction
|
||||||
|
const status = await getDispenserStatusFromGraph(tokenAddress)
|
||||||
|
assert(status.data.dispenser.datatoken.id === tokenAddress.toLowerCase())
|
||||||
|
assert(status.data.dispenser.owner.id === alice.getId().toLowerCase())
|
||||||
|
assert(status.data.dispenser.isTrueMinter === false)
|
||||||
|
assert(status.data.dispenser.minterApproved === false)
|
||||||
|
assert(status.data.dispenser.active === true)
|
||||||
|
assert(status.data.dispenser.balance === '0')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Alice should make the dispenser a minter', async () => {
|
||||||
|
const tx = await ocean.OceanDispenser.makeMinter(
|
||||||
|
tokenAddress,
|
||||||
|
alice.getId()
|
||||||
|
)
|
||||||
|
assert(tx, 'Cannot make dispenser a minter')
|
||||||
|
await sleep(3000) // let graph ingest our transaction
|
||||||
|
const status = await getDispenserStatusFromGraph(tokenAddress)
|
||||||
|
assert(status.data.dispenser.datatoken.id === tokenAddress.toLowerCase())
|
||||||
|
assert(status.data.dispenser.owner.id === alice.getId().toLowerCase())
|
||||||
|
assert(status.data.dispenser.isTrueMinter === true)
|
||||||
|
assert(status.data.dispenser.minterApproved === true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Bob requests datatokens', async () => {
|
||||||
|
const tx = await ocean.OceanDispenser.dispense(
|
||||||
|
tokenAddress,
|
||||||
|
bob.getId(),
|
||||||
|
'1'
|
||||||
|
)
|
||||||
|
assert(tx, 'Bob failed to get 1DT')
|
||||||
|
await sleep(3000) // let graph ingest our transaction
|
||||||
|
const id = tx.transactionHash.toLowerCase()
|
||||||
|
const query = {
|
||||||
|
query: `query DispenserHistory {
|
||||||
|
dispenserTransactions(orderBy: timestamp, orderDirection: desc,
|
||||||
|
where: {tx: "${id}"}) {
|
||||||
|
datatoken{id},
|
||||||
|
user{id},
|
||||||
|
amount,
|
||||||
|
block,
|
||||||
|
timestamp,
|
||||||
|
tx,
|
||||||
|
type
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(subgraphUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(query)
|
||||||
|
})
|
||||||
|
const result = await response.json()
|
||||||
|
|
||||||
|
assert(result.data.dispenserTransactions[0].type === 'dispense')
|
||||||
|
})
|
||||||
|
it('Alice calls removeMinter role and checks if she is the new minter', async () => {
|
||||||
|
const tx = await ocean.OceanDispenser.cancelMinter(
|
||||||
|
tokenAddress,
|
||||||
|
alice.getId()
|
||||||
|
)
|
||||||
|
assert(tx, 'Cannot cancel minter role')
|
||||||
|
await sleep(3000) // let graph ingest our transaction
|
||||||
|
const status = await getDispenserStatusFromGraph(tokenAddress)
|
||||||
|
assert(status.data.dispenser.datatoken.id === tokenAddress.toLowerCase())
|
||||||
|
assert(status.data.dispenser.owner.id === alice.getId().toLowerCase())
|
||||||
|
assert(status.data.dispenser.isTrueMinter === false)
|
||||||
|
assert(status.data.dispenser.minterApproved === false)
|
||||||
|
assert(status.data.dispenser.active === true)
|
||||||
|
})
|
||||||
|
it('Alice deactivates the dispenser', async () => {
|
||||||
|
const tx = await ocean.OceanDispenser.deactivate(
|
||||||
|
tokenAddress,
|
||||||
|
alice.getId()
|
||||||
|
)
|
||||||
|
assert(tx, 'Cannot make dispenser a minter')
|
||||||
|
await sleep(3000) // let graph ingest our transaction
|
||||||
|
const status = await getDispenserStatusFromGraph(tokenAddress)
|
||||||
|
assert(status.data.dispenser.datatoken.id === tokenAddress.toLowerCase())
|
||||||
|
assert(status.data.dispenser.owner.id === alice.getId().toLowerCase())
|
||||||
|
assert(status.data.dispenser.active === false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Alice creates a dispenser without minter role', async () => {
|
||||||
|
const tx = await ocean.OceanDispenser.activate(
|
||||||
|
tokenAddress2,
|
||||||
|
'1',
|
||||||
|
'1',
|
||||||
|
alice.getId()
|
||||||
|
)
|
||||||
|
assert(tx, 'Cannot activate dispenser')
|
||||||
|
await sleep(3000) // let graph ingest our transaction
|
||||||
|
const status = await getDispenserStatusFromGraph(tokenAddress2)
|
||||||
|
assert(status.data.dispenser.datatoken.id === tokenAddress2.toLowerCase())
|
||||||
|
assert(status.data.dispenser.owner.id === alice.getId().toLowerCase())
|
||||||
|
assert(status.data.dispenser.isTrueMinter === false)
|
||||||
|
assert(status.data.dispenser.minterApproved === false)
|
||||||
|
assert(status.data.dispenser.active === true)
|
||||||
|
})
|
||||||
|
it('Alice withdraws all datatokens', async () => {
|
||||||
|
const mintTx = await ocean.datatokens.mint(
|
||||||
|
tokenAddress2,
|
||||||
|
alice.getId(),
|
||||||
|
'10',
|
||||||
|
ocean.OceanDispenser.dispenserAddress
|
||||||
|
)
|
||||||
|
assert(mintTx, 'Alice cannot mint tokens')
|
||||||
|
const tx = await ocean.OceanDispenser.ownerWithdraw(
|
||||||
|
tokenAddress2,
|
||||||
|
alice.getId()
|
||||||
|
)
|
||||||
|
assert(tx, 'Alice failed to withdraw all her tokens')
|
||||||
|
await sleep(3000) // let graph ingest our transaction
|
||||||
|
const status = await getDispenserStatusFromGraph(tokenAddress2)
|
||||||
|
assert(status.data.dispenser.datatoken.id === tokenAddress2.toLowerCase())
|
||||||
|
assert(status.data.dispenser.owner.id === alice.getId().toLowerCase())
|
||||||
|
assert(status.data.dispenser.isTrueMinter === false)
|
||||||
|
assert(status.data.dispenser.minterApproved === false)
|
||||||
|
assert(status.data.dispenser.active === true)
|
||||||
|
assert(status.data.dispenser.balance === '0')
|
||||||
|
const id = tx.transactionHash.toLowerCase()
|
||||||
|
const query = {
|
||||||
|
query: `query DispenserHistory {
|
||||||
|
dispenserTransactions(orderBy: timestamp, orderDirection: desc,
|
||||||
|
where: {tx: "${id}"}) {
|
||||||
|
datatoken{id},
|
||||||
|
user{id},
|
||||||
|
amount,
|
||||||
|
block,
|
||||||
|
timestamp,
|
||||||
|
tx,
|
||||||
|
type
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
// console.log(query)
|
||||||
|
const response = await fetch(subgraphUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(query)
|
||||||
|
})
|
||||||
|
const result = await response.json()
|
||||||
|
assert(result.data.dispenserTransactions[0].type === 'withdraw')
|
||||||
|
})
|
||||||
|
})
|
@ -7,11 +7,20 @@ const web3 = new Web3('http://127.0.0.1:8545')
|
|||||||
const subgraphUrl =
|
const subgraphUrl =
|
||||||
'http://localhost:9000/subgraphs/name/oceanprotocol/ocean-subgraph'
|
'http://localhost:9000/subgraphs/name/oceanprotocol/ocean-subgraph'
|
||||||
|
|
||||||
|
function sleep(ms: number) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
use(spies)
|
use(spies)
|
||||||
|
|
||||||
describe('Ending tests', () => {
|
describe('Ending tests', () => {
|
||||||
let result: any
|
let result: any
|
||||||
|
let lastblock
|
||||||
it('Get Graph status', async () => {
|
it('Get Graph status', async () => {
|
||||||
|
await sleep(1000) // let graph ingest our last transactions
|
||||||
|
lastblock = await web3.eth.getBlockNumber()
|
||||||
const query = {
|
const query = {
|
||||||
query: `query {
|
query: `query {
|
||||||
_meta{hasIndexingErrors,
|
_meta{hasIndexingErrors,
|
||||||
@ -31,7 +40,6 @@ describe('Ending tests', () => {
|
|||||||
assert(result.data._meta.hasIndexingErrors == false)
|
assert(result.data._meta.hasIndexingErrors == false)
|
||||||
})
|
})
|
||||||
it('Make sure that graph has synced to last block', async () => {
|
it('Make sure that graph has synced to last block', async () => {
|
||||||
const lastblock = await web3.eth.getBlockNumber()
|
|
||||||
assert(result.data._meta.block.number === lastblock)
|
assert(result.data._meta.block.number === lastblock)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user