11const conseiljs = require ( 'conseiljs' )
22const fetch = require ( 'node-fetch' )
33const log = require ( 'loglevel' )
4+ const BigNumber = require ( 'bignumber.js' )
45
56const logger = log . getLogger ( 'conseiljs' )
67logger . setLevel ( 'error' , false )
@@ -20,7 +21,7 @@ const mainnet = require('./config').networkConfig
2021 */
2122const getCollectionForAddress = async ( address ) => {
2223 let collectionQuery = conseiljs . ConseilQueryBuilder . blankQuery ( ) ;
23- collectionQuery = conseiljs . ConseilQueryBuilder . addFields ( collectionQuery , 'key' , 'value' ) ;
24+ collectionQuery = conseiljs . ConseilQueryBuilder . addFields ( collectionQuery , 'key' , 'value' , 'operation_group_id' ) ;
2425 collectionQuery = conseiljs . ConseilQueryBuilder . addPredicate ( collectionQuery , 'big_map_id' , conseiljs . ConseilOperator . EQ , [ mainnet . nftLedger ] )
2526 collectionQuery = conseiljs . ConseilQueryBuilder . addPredicate ( collectionQuery , 'key' , conseiljs . ConseilOperator . STARTSWITH , [
2627 `Pair 0x${ conseiljs . TezosMessageUtils . writeAddress ( address ) } ` ,
@@ -30,10 +31,14 @@ const getCollectionForAddress = async (address) => {
3031
3132 const collectionResult = await conseiljs . TezosConseilClient . getTezosEntityData ( { url : conseilServer , apiKey : conseilApiKey , network : 'mainnet' } , 'mainnet' , 'big_map_contents' , collectionQuery ) ;
3233 let collection = collectionResult . map ( ( i ) => {
33- return { piece : i . key . toString ( ) . replace ( / .* ( [ 0 - 9 ] { 1 , } $ ) / , '$1' ) , amount : Number ( i . value ) }
34+ return {
35+ piece : i [ 'key' ] . toString ( ) . replace ( / .* ( [ 0 - 9 ] { 1 , } $ ) / , '$1' ) ,
36+ amount : Number ( i [ 'value' ] ) ,
37+ opId : i [ 'operation_group_id' ]
38+ }
3439 } )
3540
36- const queryChunks = chunkArray ( collection . map ( i => i . piece ) , 20 ) // NOTE: consider increasing this number somewhat
41+ const queryChunks = chunkArray ( collection . map ( i => i . piece ) , 50 ) // NOTE: consider increasing this number somewhat
3742 const makeObjectQuery = ( keys ) => {
3843 let mintedObjectsQuery = conseiljs . ConseilQueryBuilder . blankQuery ( ) ;
3944 mintedObjectsQuery = conseiljs . ConseilQueryBuilder . addFields ( mintedObjectsQuery , 'key_hash' , 'value' ) ;
@@ -55,17 +60,84 @@ const getCollectionForAddress = async (address) => {
5560 objectIpfsMap [ objectId ] = ipfsHash
5661 } ) ) ) )
5762
58- collection = collection . map ( i => { return {
59- ipfsHash : objectIpfsMap [ i . piece . toString ( ) ] ,
60- ...i
63+ const operationGroupIds = collectionResult . map ( ( r ) => r . operation_group_id )
64+ const priceQueryChunks = chunkArray ( operationGroupIds , 30 )
65+ const makeLastPriceQuery = ( opIds ) => {
66+ let lastPriceQuery = conseiljs . ConseilQueryBuilder . blankQuery ( ) ;
67+ lastPriceQuery = conseiljs . ConseilQueryBuilder . addFields ( lastPriceQuery , 'timestamp' , 'amount' , 'operation_group_hash' , 'parameters_entrypoints' , 'parameters' ) ;
68+ lastPriceQuery = conseiljs . ConseilQueryBuilder . addPredicate ( lastPriceQuery , 'kind' , conseiljs . ConseilOperator . EQ , [ 'transaction' ] ) ;
69+ lastPriceQuery = conseiljs . ConseilQueryBuilder . addPredicate ( lastPriceQuery , 'status' , conseiljs . ConseilOperator . EQ , [ 'applied' ] ) ;
70+ lastPriceQuery = conseiljs . ConseilQueryBuilder . addPredicate ( lastPriceQuery , 'internal' , conseiljs . ConseilOperator . EQ , [ 'false' ] ) ;
71+ lastPriceQuery = conseiljs . ConseilQueryBuilder . addPredicate ( lastPriceQuery , 'operation_group_hash' , opIds . length > 1 ? conseiljs . ConseilOperator . IN : conseiljs . ConseilOperator . EQ , opIds ) ;
72+ lastPriceQuery = conseiljs . ConseilQueryBuilder . setLimit ( lastPriceQuery , opIds . length ) ;
73+
74+ return lastPriceQuery ;
75+ }
76+
77+ const priceQueries = priceQueryChunks . map ( ( c ) => makeLastPriceQuery ( c ) )
78+ const priceMap = { } ;
79+ await Promise . all (
80+ priceQueries . map (
81+ async ( q ) =>
82+ await conseiljs . TezosConseilClient . getTezosEntityData ( { url : conseilServer , apiKey : conseilApiKey , network : 'mainnet' } , 'mainnet' , 'operations' , q ) . then ( ( result ) =>
83+ result . map ( ( row ) => {
84+ let amount = 0 ;
85+ const action = row . parameters_entrypoints ;
86+
87+ if ( action === 'collect' ) {
88+ amount = Number ( row . parameters . toString ( ) . replace ( / ^ P a i r ( [ 0 - 9 ] + ) [ 0 - 9 ] + / , '$1' ) ) ;
89+ } else if ( action === 'transfer' ) {
90+ amount = Number (
91+ row . parameters
92+ . toString ( )
93+ . replace (
94+ / [ { ] P a i r \" [ 1 - 9 A - H J - N P - Z a - k m - z ] { 36 } \" [ { ] P a i r \" [ 1 - 9 A - H J - N P - Z a - k m - z ] { 36 } \" [ ( ] P a i r [ 0 - 9 ] + [ 0 - 9 ] + [ ) ] [ } ] [ } ] / ,
95+ '$1'
96+ )
97+ ) ;
98+ }
99+
100+ priceMap [ row . operation_group_hash ] = {
101+ price : new BigNumber ( row . amount ) ,
102+ amount,
103+ timestamp : row . timestamp ,
104+ action,
105+ } ;
106+ } )
107+ )
108+ )
109+ )
110+
111+ collection = collection . map ( i => {
112+ let price = 0
113+ let receivedOn = new Date ( )
114+ let action = ''
115+
116+ try {
117+ const priceRecord = priceMap [ i . opId ]
118+ price = priceRecord . price . dividedToIntegerBy ( priceRecord . amount ) . toNumber ( )
119+ receivedOn = new Date ( priceRecord . timestamp )
120+ action = priceRecord . action === 'collect' ? 'Purchased' : 'Received'
121+ } catch {
122+ //
123+ }
124+
125+ delete i . opId
126+
127+ return {
128+ price : isNaN ( price ) ? 0 : price ,
129+ receivedOn,
130+ action,
131+ ipfsHash : objectIpfsMap [ i . piece . toString ( ) ] ,
132+ ...i
61133 } } )
62134
63135 return collection . sort ( ( a , b ) => parseInt ( b . piece ) - parseInt ( a . piece ) ) // sort descending by id – most-recently minted art first
64136}
65137
66138const gethDaoBalanceForAddress = async ( address ) => {
67- let hDaoBalanceQuery = conseiljs . ConseilQueryBuilder . blankQuery ( ) ;
68- hDaoBalanceQuery = conseiljs . ConseilQueryBuilder . addFields ( hDaoBalanceQuery , 'value' ) ;
139+ let hDaoBalanceQuery = conseiljs . ConseilQueryBuilder . blankQuery ( )
140+ hDaoBalanceQuery = conseiljs . ConseilQueryBuilder . addFields ( hDaoBalanceQuery , 'value' )
69141 hDaoBalanceQuery = conseiljs . ConseilQueryBuilder . addPredicate ( hDaoBalanceQuery , 'big_map_id' , conseiljs . ConseilOperator . EQ , [ mainnet . daoLedger ] )
70142 hDaoBalanceQuery = conseiljs . ConseilQueryBuilder . addPredicate ( hDaoBalanceQuery , 'key' , conseiljs . ConseilOperator . EQ , [
71143 `Pair 0x${ conseiljs . TezosMessageUtils . writeAddress ( address ) } 0`
@@ -76,7 +148,7 @@ const gethDaoBalanceForAddress = async (address) => {
76148 let balance = 0
77149
78150 try {
79- const balanceResult = await conseiljs . TezosConseilClient . getTezosEntityData ( { url : conseilServer , apiKey : conseilApiKey , network : 'mainnet' } , 'mainnet' , 'big_map_contents' , hDaoBalanceQuery ) ;
151+ const balanceResult = await conseiljs . TezosConseilClient . getTezosEntityData ( { url : conseilServer , apiKey : conseilApiKey , network : 'mainnet' } , 'mainnet' , 'big_map_contents' , hDaoBalanceQuery )
80152 balance = balanceResult [ 0 ] [ 'value' ] // TODO: consider bigNumber here, for the moment there is no reason for it
81153 } catch ( error ) {
82154 console . log ( `gethDaoBalanceForAddress failed for ${ JSON . stringify ( hDaoBalanceQuery ) } with ${ error } ` )
@@ -92,8 +164,8 @@ const gethDaoBalanceForAddress = async (address) => {
92164 * @returns
93165 */
94166const getArtisticOutputForAddress = async ( address ) => {
95- let mintOperationQuery = conseiljs . ConseilQueryBuilder . blankQuery ( ) ;
96- mintOperationQuery = conseiljs . ConseilQueryBuilder . addFields ( mintOperationQuery , 'operation_group_hash' ) ;
167+ let mintOperationQuery = conseiljs . ConseilQueryBuilder . blankQuery ( )
168+ mintOperationQuery = conseiljs . ConseilQueryBuilder . addFields ( mintOperationQuery , 'operation_group_hash' )
97169 mintOperationQuery = conseiljs . ConseilQueryBuilder . addPredicate ( mintOperationQuery , 'kind' , conseiljs . ConseilOperator . EQ , [ 'transaction' ] )
98170 mintOperationQuery = conseiljs . ConseilQueryBuilder . addPredicate ( mintOperationQuery , 'timestamp' , conseiljs . ConseilOperator . AFTER , [ 1612240919000 ] ) // 2021 Feb 1
99171 mintOperationQuery = conseiljs . ConseilQueryBuilder . addPredicate ( mintOperationQuery , 'status' , conseiljs . ConseilOperator . EQ , [ 'applied' ] )
@@ -107,14 +179,14 @@ const getArtisticOutputForAddress = async (address) => {
107179 { url : conseilServer , apiKey : conseilApiKey , network : 'mainnet' } ,
108180 'mainnet' ,
109181 'operations' ,
110- mintOperationQuery ) ;
182+ mintOperationQuery )
111183
112184 const operationGroupIds = mintOperationResult . map ( r => r [ 'operation_group_hash' ] )
113185 const queryChunks = chunkArray ( operationGroupIds , 30 )
114186
115187 const makeObjectQuery = ( opIds ) => {
116- let mintedObjectsQuery = conseiljs . ConseilQueryBuilder . blankQuery ( ) ;
117- mintedObjectsQuery = conseiljs . ConseilQueryBuilder . addFields ( mintedObjectsQuery , 'key_hash' , 'value' ) ;
188+ let mintedObjectsQuery = conseiljs . ConseilQueryBuilder . blankQuery ( )
189+ mintedObjectsQuery = conseiljs . ConseilQueryBuilder . addFields ( mintedObjectsQuery , 'key_hash' , 'value' )
118190 mintedObjectsQuery = conseiljs . ConseilQueryBuilder . addPredicate ( mintedObjectsQuery , 'big_map_id' , conseiljs . ConseilOperator . EQ , [ mainnet . nftMetadataMap ] )
119191 mintedObjectsQuery = conseiljs . ConseilQueryBuilder . addPredicate ( mintedObjectsQuery , 'operation_group_id' , ( opIds . length > 1 ? conseiljs . ConseilOperator . IN : conseiljs . ConseilOperator . EQ ) , opIds )
120192 mintedObjectsQuery = conseiljs . ConseilQueryBuilder . setLimit ( mintedObjectsQuery , opIds . length )
@@ -222,7 +294,6 @@ const getArtisticUniverse = async (offset) => {
222294 * @param {number } objectId
223295 * @returns
224296 */
225-
226297const getObjectById = async ( objectId ) => {
227298 let objectQuery = conseiljs . ConseilQueryBuilder . blankQuery ( ) ;
228299 objectQuery = conseiljs . ConseilQueryBuilder . addFields ( objectQuery , 'value' ) ;
0 commit comments