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
|
||||
|
||||
# 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
|
||||
```bash
|
||||
npm run codegen
|
||||
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": {
|
||||
"version": "0.5.16",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.16.tgz",
|
||||
"integrity": "sha512-p7aFIUT8RVoMzdPP7ML8G08BnQ09syywKjOT16hqJm0GmofunEuVffUXbryG4EkQ+qRbf/zeoxSmesi79kQXlA=="
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.6.2.tgz",
|
||||
"integrity": "sha512-J6amHsmVbdc2rAwbUYOaY7inLV13GxPIiqbsLF78nmdIvhhGDhT2LYMyfQtxkMwQzYDP6EzD4albCgOXlWM15g=="
|
||||
},
|
||||
"@oceanprotocol/lib": {
|
||||
"version": "0.14.8",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.14.8.tgz",
|
||||
"integrity": "sha512-eqab5iEgowyIM/LcDDs6xhZo/KToOmVw0betjXLG0+g70zS8R6XL2RHzCpFyutSdf/cH0w/ltPUfR8ZBElIyhQ==",
|
||||
"version": "0.14.9",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.14.9.tgz",
|
||||
"integrity": "sha512-PUNbsryrm4614CbvalP2CZS9LZjvWfqopTdb91Rz4vLbnqinioELSFXNq+hiSkyuFqAy0szG0wueBcW8mwFbSg==",
|
||||
"requires": {
|
||||
"@ethereum-navigator/navigator": "^0.5.2",
|
||||
"@oceanprotocol/contracts": "0.5.16",
|
||||
"@oceanprotocol/contracts": "^0.6.2",
|
||||
"@types/crypto-js": "^4.0.1",
|
||||
"cross-fetch": "^3.1.2",
|
||||
"crypto-js": "^4.0.0",
|
||||
@ -5163,9 +5163,9 @@
|
||||
"integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg=="
|
||||
},
|
||||
"is-bigint": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz",
|
||||
"integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg=="
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
|
||||
"integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA=="
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
@ -5182,11 +5182,32 @@
|
||||
"integrity": "sha1-o9fZb+HD/wZex84nwsIea6ksGDI="
|
||||
},
|
||||
"is-boolean-object": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz",
|
||||
"integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
|
||||
"integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
|
||||
"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": {
|
||||
@ -5252,9 +5273,9 @@
|
||||
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
|
||||
},
|
||||
"is-generator-function": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz",
|
||||
"integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ=="
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz",
|
||||
"integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A=="
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.1",
|
||||
@ -5413,9 +5434,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"is-number-object": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz",
|
||||
"integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw=="
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
|
||||
"integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw=="
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "2.0.0",
|
||||
@ -5566,12 +5587,19 @@
|
||||
"integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz",
|
||||
"integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==",
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
|
||||
"integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
|
||||
"requires": {
|
||||
"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": {
|
||||
@ -9818,9 +9846,9 @@
|
||||
}
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz",
|
||||
"integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==",
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz",
|
||||
"integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==",
|
||||
"requires": {
|
||||
"node-gyp-build": "^4.2.0"
|
||||
}
|
||||
|
@ -54,7 +54,7 @@
|
||||
"typescript": "^4.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@oceanprotocol/lib": "^0.14.8",
|
||||
"@oceanprotocol/lib": "^0.14.9",
|
||||
"cross-fetch": "^3.1.4"
|
||||
},
|
||||
"repository": {
|
||||
|
366
schema.graphql
366
schema.graphql
@ -1,239 +1,255 @@
|
||||
type PoolFactory @entity {
|
||||
id: ID!
|
||||
id: ID!
|
||||
|
||||
totalValueLocked: BigDecimal # total value from all pools expressed in OCEAN
|
||||
|
||||
totalOceanLiquidity: BigDecimal! # Total of OCEAN liquidity from all pools
|
||||
totalSwapVolume: BigDecimal! # All the swap volume in Ocean
|
||||
totalSwapFee: BigDecimal! # All the swap fee in Ocean
|
||||
|
||||
poolCount: Int! # Number of pools
|
||||
finalizedPoolCount: Int! # Number of finalized pools
|
||||
|
||||
pools: [Pool!] @derivedFrom(field: "factoryID")
|
||||
totalValueLocked: BigDecimal # total value from all pools expressed in OCEAN
|
||||
totalOceanLiquidity: BigDecimal! # Total of OCEAN liquidity from all pools
|
||||
totalSwapVolume: BigDecimal! # All the swap volume in Ocean
|
||||
totalSwapFee: BigDecimal! # All the swap fee in Ocean
|
||||
poolCount: Int! # Number of pools
|
||||
finalizedPoolCount: Int! # Number of finalized pools
|
||||
pools: [Pool!] @derivedFrom(field: "factoryID")
|
||||
}
|
||||
|
||||
type Pool @entity {
|
||||
id: ID! # Pool address
|
||||
factoryID: PoolFactory!
|
||||
controller: Bytes! # Controller address
|
||||
publicSwap: Boolean! # isPublicSwap
|
||||
finalized: Boolean! # isFinalized
|
||||
symbol: String # Pool token symbol
|
||||
name: String # Pool token name
|
||||
cap: BigInt # Maximum supply if any
|
||||
active: Boolean! # isActive
|
||||
swapFee: BigDecimal! # Swap Fees
|
||||
id: ID! # Pool address
|
||||
factoryID: PoolFactory!
|
||||
controller: Bytes! # Controller address
|
||||
publicSwap: Boolean! # isPublicSwap
|
||||
finalized: Boolean! # isFinalized
|
||||
symbol: String # Pool token symbol
|
||||
name: String # Pool token name
|
||||
cap: BigInt # Maximum supply if any
|
||||
active: Boolean! # isActive
|
||||
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!
|
||||
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!
|
||||
|
||||
tokenCount: BigInt! # Number of tokens in the pool
|
||||
holderCount: BigInt! # Number of addresses holding a positive balance of pool shares
|
||||
joinCount: BigInt! # liquidity has been added
|
||||
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")
|
||||
tokenCount: BigInt! # Number of tokens in the pool
|
||||
holderCount: BigInt! # Number of addresses holding a positive balance of pool shares
|
||||
joinCount: BigInt! # liquidity has been added
|
||||
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 {
|
||||
id: ID! # poolId + token address
|
||||
poolId: Pool!
|
||||
tokenId: Datatoken
|
||||
tokenAddress: String
|
||||
balance: BigDecimal!
|
||||
denormWeight: BigDecimal!
|
||||
id: ID! # poolId + token address
|
||||
poolId: Pool!
|
||||
tokenId: Datatoken
|
||||
tokenAddress: String
|
||||
balance: BigDecimal!
|
||||
denormWeight: BigDecimal!
|
||||
}
|
||||
|
||||
type PoolShare @entity {
|
||||
id: ID! # poolId + userAddress
|
||||
userAddress: User!
|
||||
poolId: Pool!
|
||||
balance: BigDecimal!
|
||||
id: ID! # poolId + userAddress
|
||||
userAddress: User!
|
||||
poolId: Pool!
|
||||
balance: BigDecimal!
|
||||
}
|
||||
|
||||
type PoolTransactionTokenValues @entity {
|
||||
id: ID! # pool tx + tokenAddress
|
||||
txId: PoolTransaction!
|
||||
poolToken: PoolToken!
|
||||
poolAddress: Pool!
|
||||
userAddress: User!
|
||||
tokenAddress: String!
|
||||
id: ID! # pool tx + tokenAddress
|
||||
txId: PoolTransaction!
|
||||
poolToken: PoolToken!
|
||||
poolAddress: Pool!
|
||||
userAddress: User!
|
||||
tokenAddress: String!
|
||||
|
||||
value: BigDecimal!
|
||||
tokenReserve: BigDecimal!
|
||||
feeValue: BigDecimal! # Swap fee value in OCEAN
|
||||
type: String!
|
||||
value: BigDecimal!
|
||||
tokenReserve: BigDecimal!
|
||||
feeValue: BigDecimal! # Swap fee value in OCEAN
|
||||
type: String!
|
||||
}
|
||||
|
||||
type PoolTransaction @entity {
|
||||
id: ID! # pool tx
|
||||
poolAddress: Pool
|
||||
userAddress: User # User address that initiates the swap
|
||||
poolAddressStr: String!
|
||||
userAddressStr: String!
|
||||
id: ID! # pool tx
|
||||
poolAddress: Pool
|
||||
userAddress: User # User address that initiates the swap
|
||||
poolAddressStr: String!
|
||||
userAddressStr: String!
|
||||
|
||||
sharesTransferAmount: BigDecimal! #
|
||||
sharesBalance: BigDecimal!
|
||||
sharesTransferAmount: BigDecimal! #
|
||||
sharesBalance: BigDecimal!
|
||||
|
||||
spotPrice: BigDecimal!
|
||||
consumePrice: BigDecimal!
|
||||
tx: Bytes!
|
||||
event: String
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
gasUsed: BigDecimal!
|
||||
gasPrice: BigDecimal!
|
||||
spotPrice: BigDecimal!
|
||||
consumePrice: BigDecimal!
|
||||
tx: Bytes!
|
||||
event: String
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
gasUsed: BigDecimal!
|
||||
gasPrice: BigDecimal!
|
||||
|
||||
oceanReserve: BigDecimal!
|
||||
datatokenReserve: BigDecimal!
|
||||
oceanReserve: BigDecimal!
|
||||
datatokenReserve: BigDecimal!
|
||||
|
||||
tokens: [PoolTransactionTokenValues!] @derivedFrom(field: "txId")
|
||||
tokens: [PoolTransactionTokenValues!] @derivedFrom(field: "txId")
|
||||
}
|
||||
|
||||
type DatatokenFactory @entity {
|
||||
id: ID!
|
||||
id: ID!
|
||||
|
||||
tokenCount: Int! # Number of datatokens
|
||||
|
||||
datatokens: [Datatoken!] @derivedFrom(field: "factoryID")
|
||||
tokenCount: Int! # Number of datatokens
|
||||
datatokens: [Datatoken!] @derivedFrom(field: "factoryID")
|
||||
}
|
||||
|
||||
type Datatoken @entity {
|
||||
id: ID! # token address
|
||||
factoryID: DatatokenFactory!
|
||||
id: ID! # token address
|
||||
factoryID: DatatokenFactory!
|
||||
|
||||
symbol: String
|
||||
name: String
|
||||
decimals: Int!
|
||||
address: String!
|
||||
cap: BigDecimal!
|
||||
supply: BigDecimal!
|
||||
minter: User!
|
||||
publisher: String!
|
||||
symbol: String
|
||||
name: String
|
||||
decimals: Int!
|
||||
address: String!
|
||||
cap: BigDecimal!
|
||||
supply: BigDecimal!
|
||||
minter: User!
|
||||
publisher: String!
|
||||
|
||||
holderCount: BigInt! # Number of addresses holding a balance of datatoken
|
||||
orderCount: BigInt! # Number of orders executed for this dataset
|
||||
metadataUpdateCount: BigInt!
|
||||
holderCount: BigInt! # Number of addresses holding a balance of datatoken
|
||||
orderCount: BigInt! # Number of orders executed for this dataset
|
||||
metadataUpdateCount: BigInt!
|
||||
|
||||
createTime: Int! # Block time datatoken was created
|
||||
tx: Bytes # Datatoken creation transaction id
|
||||
|
||||
balances: [TokenBalance!] @derivedFrom(field: "datatokenId")
|
||||
orders: [TokenOrder!] @derivedFrom(field: "datatokenId")
|
||||
updates: [MetadataUpdate!] @derivedFrom(field: "datatokenId") # list of MetadataUpdate objects
|
||||
createTime: Int! # Block time datatoken was created
|
||||
tx: Bytes # Datatoken creation transaction id
|
||||
balances: [TokenBalance!] @derivedFrom(field: "datatokenId")
|
||||
orders: [TokenOrder!] @derivedFrom(field: "datatokenId")
|
||||
updates: [MetadataUpdate!] @derivedFrom(field: "datatokenId") # list of MetadataUpdate objects
|
||||
}
|
||||
|
||||
type MetadataUpdate @entity {
|
||||
id: ID! # update tx + datatokenAddress
|
||||
datatokenId: Datatoken!
|
||||
id: ID! # update tx + datatokenAddress
|
||||
datatokenId: Datatoken!
|
||||
|
||||
datatokenAddress: String!
|
||||
userAddress: String!
|
||||
datatokenAddress: String!
|
||||
userAddress: String!
|
||||
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
tx: Bytes!
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
tx: Bytes!
|
||||
}
|
||||
|
||||
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!
|
||||
payer: User!
|
||||
amount: BigDecimal!
|
||||
serviceId: Int!
|
||||
marketFeeCollector: User
|
||||
marketFee: BigDecimal!
|
||||
|
||||
timestamp: Int!
|
||||
tx: Bytes
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
tx: Bytes
|
||||
block: Int!
|
||||
}
|
||||
|
||||
type TokenBalance @entity {
|
||||
id: ID! # datatokenId + userAddress
|
||||
userAddress: User!
|
||||
datatokenId: Datatoken!
|
||||
balance: BigDecimal!
|
||||
id: ID! # datatokenId + userAddress
|
||||
userAddress: User!
|
||||
datatokenId: Datatoken!
|
||||
balance: BigDecimal!
|
||||
}
|
||||
|
||||
type TokenTransaction @entity {
|
||||
id: ID! # Log ID
|
||||
id: ID! # Log ID
|
||||
event: String
|
||||
datatokenAddress: Datatoken
|
||||
userAddress: User
|
||||
|
||||
event: String
|
||||
datatokenAddress: Datatoken
|
||||
userAddress: User
|
||||
|
||||
block: Int!
|
||||
gasUsed: BigDecimal!
|
||||
gasPrice: BigDecimal!
|
||||
timestamp: Int!
|
||||
tx: Bytes!
|
||||
block: Int!
|
||||
gasUsed: BigDecimal!
|
||||
gasPrice: BigDecimal!
|
||||
timestamp: Int!
|
||||
tx: Bytes!
|
||||
}
|
||||
|
||||
type User @entity {
|
||||
id: ID!
|
||||
id: ID!
|
||||
|
||||
sharesOwned: [PoolShare!] @derivedFrom(field: "userAddress")
|
||||
tokenBalancesOwned: [TokenBalance!] @derivedFrom(field: "userAddress")
|
||||
tokensOwned: [Datatoken!] @derivedFrom(field: "minter")
|
||||
poolTransactions: [PoolTransaction!] @derivedFrom(field: "userAddress")
|
||||
poolTransactionsTokenValues: [PoolTransactionTokenValues!] @derivedFrom(field: "userAddress")
|
||||
tokenTransactions: [TokenTransaction!] @derivedFrom(field: "userAddress")
|
||||
orders: [TokenOrder!] @derivedFrom(field: "payer")
|
||||
freSwaps: [FixedRateExchangeSwap!] @derivedFrom(field: "by")
|
||||
sharesOwned: [PoolShare!] @derivedFrom(field: "userAddress")
|
||||
tokenBalancesOwned: [TokenBalance!] @derivedFrom(field: "userAddress")
|
||||
tokensOwned: [Datatoken!] @derivedFrom(field: "minter")
|
||||
poolTransactions: [PoolTransaction!] @derivedFrom(field: "userAddress")
|
||||
poolTransactionsTokenValues: [PoolTransactionTokenValues!]
|
||||
@derivedFrom(field: "userAddress")
|
||||
tokenTransactions: [TokenTransaction!] @derivedFrom(field: "userAddress")
|
||||
orders: [TokenOrder!] @derivedFrom(field: "payer")
|
||||
freSwaps: [FixedRateExchangeSwap!] @derivedFrom(field: "by")
|
||||
}
|
||||
|
||||
type FixedRateExchange @entity {
|
||||
id: ID! # fixed rate exchange id
|
||||
exchangeOwner: User!
|
||||
datatoken: Datatoken!
|
||||
baseToken: String!
|
||||
rate: BigDecimal!
|
||||
active: Boolean!
|
||||
updates: [FixedRateExchangeUpdate!] @derivedFrom(field: "exchangeId")
|
||||
swaps: [FixedRateExchangeSwap!] @derivedFrom(field: "exchangeId")
|
||||
id: ID! # fixed rate exchange id
|
||||
exchangeOwner: User!
|
||||
datatoken: Datatoken!
|
||||
baseToken: String!
|
||||
rate: BigDecimal!
|
||||
active: Boolean!
|
||||
updates: [FixedRateExchangeUpdate!] @derivedFrom(field: "exchangeId")
|
||||
swaps: [FixedRateExchangeSwap!] @derivedFrom(field: "exchangeId")
|
||||
}
|
||||
|
||||
type FixedRateExchangeUpdate @entity {
|
||||
id: ID!
|
||||
exchangeId: FixedRateExchange!
|
||||
oldRate: BigDecimal!
|
||||
newRate: BigDecimal!
|
||||
oldActive: Boolean!
|
||||
newActive: Boolean!
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
tx: Bytes!
|
||||
id: ID!
|
||||
exchangeId: FixedRateExchange!
|
||||
oldRate: BigDecimal!
|
||||
newRate: BigDecimal!
|
||||
oldActive: Boolean!
|
||||
newActive: Boolean!
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
tx: Bytes!
|
||||
}
|
||||
|
||||
type FixedRateExchangeSwap @entity {
|
||||
id: ID!
|
||||
exchangeId: FixedRateExchange!
|
||||
by: User!
|
||||
baseTokenAmount: BigDecimal!
|
||||
dataTokenAmount: BigDecimal!
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
tx: Bytes!
|
||||
id: ID!
|
||||
exchangeId: FixedRateExchange!
|
||||
by: User!
|
||||
baseTokenAmount: BigDecimal!
|
||||
dataTokenAmount: BigDecimal!
|
||||
block: Int!
|
||||
timestamp: Int!
|
||||
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
|
||||
FixedRateExchange,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
Metadata
|
||||
Metadata,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
Dispenser
|
||||
} = data.development
|
||||
let subgraph = fs.readFileSync('subgraph.yaml', 'utf8')
|
||||
if (!data) {
|
||||
@ -38,6 +40,11 @@ async function replaceContractAddresses() {
|
||||
/0x608d05214E42722B94a54cF6114d4840FCfF84e1/g,
|
||||
FixedRateExchange
|
||||
)
|
||||
// dispenser
|
||||
subgraph = subgraph.replace(
|
||||
/0xDEfD0018969cd2d4E648209F876ADe184815f038/g,
|
||||
Dispenser
|
||||
)
|
||||
// network
|
||||
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
|
||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||
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:
|
||||
- kind: ethereum/contract
|
||||
name: Pool
|
||||
|
@ -94,6 +94,36 @@ dataSources:
|
||||
handler: handleExchangeRateChanged
|
||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||
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:
|
||||
- kind: ethereum/contract
|
||||
name: Pool
|
||||
|
@ -94,6 +94,36 @@ dataSources:
|
||||
handler: handleExchangeRateChanged
|
||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||
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:
|
||||
- kind: ethereum/contract
|
||||
name: Pool
|
||||
|
@ -94,6 +94,36 @@ dataSources:
|
||||
handler: handleExchangeRateChanged
|
||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||
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:
|
||||
- kind: ethereum/contract
|
||||
name: Pool
|
||||
|
@ -94,6 +94,36 @@ dataSources:
|
||||
handler: handleExchangeRateChanged
|
||||
- event: Swapped(indexed bytes32,indexed address,uint256,uint256)
|
||||
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:
|
||||
- kind: ethereum/contract
|
||||
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 =
|
||||
'http://localhost:9000/subgraphs/name/oceanprotocol/ocean-subgraph'
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms)
|
||||
})
|
||||
}
|
||||
|
||||
use(spies)
|
||||
|
||||
describe('Ending tests', () => {
|
||||
let result: any
|
||||
let lastblock
|
||||
it('Get Graph status', async () => {
|
||||
await sleep(1000) // let graph ingest our last transactions
|
||||
lastblock = await web3.eth.getBlockNumber()
|
||||
const query = {
|
||||
query: `query {
|
||||
_meta{hasIndexingErrors,
|
||||
@ -31,7 +40,6 @@ describe('Ending tests', () => {
|
||||
assert(result.data._meta.hasIndexingErrors == false)
|
||||
})
|
||||
it('Make sure that graph has synced to last block', async () => {
|
||||
const lastblock = await web3.eth.getBlockNumber()
|
||||
assert(result.data._meta.block.number === lastblock)
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user