@audius/sdk 2.0.3-beta.6 → 2.0.3-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/Account.d.ts +26 -0
- package/dist/api/Users.d.ts +20 -0
- package/dist/core.js +5 -0
- package/dist/core.js.map +1 -1
- package/dist/index.cjs.js +2658 -932
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +2646 -920
- package/dist/index.esm.js.map +1 -1
- package/dist/legacy.js +2656 -929
- package/dist/legacy.js.map +1 -1
- package/dist/native-libs.js +2647 -921
- package/dist/native-libs.js.map +1 -1
- package/dist/services/creatorNode/CreatorNode.d.ts +3 -7
- package/dist/services/dataContracts/IPLDBlacklistFactoryClient.d.ts +17 -0
- package/dist/services/dataContracts/PlaylistFactoryClient.d.ts +22 -0
- package/dist/services/dataContracts/RegistryClient.d.ts +15 -0
- package/dist/services/dataContracts/SocialFeatureFactoryClient.d.ts +11 -0
- package/dist/services/dataContracts/TrackFactoryClient.d.ts +23 -0
- package/dist/services/dataContracts/UserFactoryClient.d.ts +64 -0
- package/dist/services/dataContracts/UserLibraryFactoryClient.d.ts +9 -0
- package/dist/services/dataContracts/UserReplicaSetManagerClient.d.ts +82 -0
- package/dist/services/discoveryProvider/DiscoveryProvider.d.ts +1 -1
- package/dist/services/discoveryProvider/requests.d.ts +2 -1
- package/dist/services/solanaAudiusData/SolanaAudiusData.d.ts +408 -0
- package/dist/services/solanaAudiusData/errors.d.ts +7 -0
- package/dist/services/solanaAudiusData/index.d.ts +2 -0
- package/dist/utils/fileHasher.d.ts +9 -2
- package/dist/utils/types.d.ts +1 -0
- package/dist/utils/utils.d.ts +1 -0
- package/package.json +2 -1
- package/src/api/Account.ts +77 -0
- package/src/api/Users.ts +181 -3
- package/src/eth-contracts/ABIs/Wormhole.json +121 -11
- package/src/services/creatorNode/CreatorNode.ts +9 -0
- package/src/services/discoveryProvider/DiscoveryProvider.ts +4 -2
- package/src/services/discoveryProvider/requests.ts +6 -1
- package/src/services/solana/rewardsAttester.ts +47 -21
- package/src/utils/fileHasher.ts +18 -3
- package/src/utils/types.ts +1 -0
package/src/api/Users.ts
CHANGED
|
@@ -68,6 +68,12 @@ export class Users extends Base {
|
|
|
68
68
|
this.getUserSubscribers = this.getUserSubscribers.bind(this)
|
|
69
69
|
this.bulkGetUserSubscribers = this.bulkGetUserSubscribers.bind(this)
|
|
70
70
|
|
|
71
|
+
this.updateMetadataV2 = this.updateMetadataV2.bind(this)
|
|
72
|
+
this.uploadProfileImagesV2 = this.uploadProfileImagesV2.bind(this)
|
|
73
|
+
this.createEntityManagerUserV2 = this.createEntityManagerUserV2.bind(this)
|
|
74
|
+
this._waitForDiscoveryToIndexUser =
|
|
75
|
+
this._waitForDiscoveryToIndexUser.bind(this)
|
|
76
|
+
|
|
71
77
|
// For adding replica set to users on sign up
|
|
72
78
|
this.assignReplicaSet = this.assignReplicaSet.bind(this)
|
|
73
79
|
|
|
@@ -440,6 +446,35 @@ export class Users extends Base {
|
|
|
440
446
|
return metadata
|
|
441
447
|
}
|
|
442
448
|
|
|
449
|
+
async uploadProfileImagesV2(
|
|
450
|
+
profilePictureFile: File,
|
|
451
|
+
coverPhotoFile: File,
|
|
452
|
+
metadata: UserMetadata
|
|
453
|
+
) {
|
|
454
|
+
let didMetadataUpdate = false
|
|
455
|
+
if (profilePictureFile) {
|
|
456
|
+
const resp = await this.creatorNode.uploadProfilePictureV2(
|
|
457
|
+
profilePictureFile
|
|
458
|
+
)
|
|
459
|
+
metadata.profile_picture_sizes = resp.id
|
|
460
|
+
didMetadataUpdate = true
|
|
461
|
+
}
|
|
462
|
+
if (coverPhotoFile) {
|
|
463
|
+
const resp = await this.creatorNode.uploadCoverPhotoV2(coverPhotoFile)
|
|
464
|
+
metadata.cover_photo_sizes = resp.id
|
|
465
|
+
didMetadataUpdate = true
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (didMetadataUpdate) {
|
|
469
|
+
await this.updateMetadataV2({
|
|
470
|
+
newMetadata: metadata,
|
|
471
|
+
userId: metadata.user_id
|
|
472
|
+
})
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return metadata
|
|
476
|
+
}
|
|
477
|
+
|
|
443
478
|
async createEntityManagerUser({ metadata }: { metadata: UserMetadata }) {
|
|
444
479
|
this.REQUIRES(Services.CREATOR_NODE)
|
|
445
480
|
const phases = {
|
|
@@ -555,6 +590,59 @@ export class Users extends Base {
|
|
|
555
590
|
}
|
|
556
591
|
}
|
|
557
592
|
|
|
593
|
+
async createEntityManagerUserV2({ metadata }: { metadata: UserMetadata }) {
|
|
594
|
+
this.REQUIRES(Services.DISCOVERY_PROVIDER)
|
|
595
|
+
|
|
596
|
+
try {
|
|
597
|
+
// Create the user with EntityMananer
|
|
598
|
+
const userId = await this._generateUserId()
|
|
599
|
+
const manageEntityResponse =
|
|
600
|
+
await this.contracts.EntityManagerClient!.manageEntity(
|
|
601
|
+
userId,
|
|
602
|
+
EntityManagerClient.EntityType.USER,
|
|
603
|
+
userId,
|
|
604
|
+
EntityManagerClient.Action.CREATE,
|
|
605
|
+
'v2'
|
|
606
|
+
)
|
|
607
|
+
await this._waitForDiscoveryToIndexUser(
|
|
608
|
+
userId,
|
|
609
|
+
manageEntityResponse.txReceipt.blockNumber
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
// Ensure metadata has expected properties
|
|
613
|
+
const newMetadata = this.cleanUserMetadata({ ...metadata })
|
|
614
|
+
this._validateUserMetadata(newMetadata)
|
|
615
|
+
|
|
616
|
+
newMetadata.is_storage_v2 = true
|
|
617
|
+
newMetadata.wallet = this.web3Manager.getWalletAddress()
|
|
618
|
+
newMetadata.user_id = userId
|
|
619
|
+
this.userStateManager.setCurrentUser({
|
|
620
|
+
...newMetadata,
|
|
621
|
+
// Initialize counts to be 0. We don't want to write this data to backends ever really
|
|
622
|
+
// (hence the cleanUserMetadata above), but we do want to make sure clients
|
|
623
|
+
// can properly "do math" on these numbers.
|
|
624
|
+
followee_count: 0,
|
|
625
|
+
follower_count: 0,
|
|
626
|
+
repost_count: 0
|
|
627
|
+
})
|
|
628
|
+
|
|
629
|
+
// Update metadata on chain to include wallet
|
|
630
|
+
const { blockHash, blockNumber } = await this.updateMetadataV2({
|
|
631
|
+
newMetadata,
|
|
632
|
+
userId
|
|
633
|
+
})
|
|
634
|
+
|
|
635
|
+
return { newMetadata, blockHash, blockNumber }
|
|
636
|
+
} catch (e) {
|
|
637
|
+
const errorMsg = `createEntityManagerUserV2() error: ${e}`
|
|
638
|
+
if (e instanceof Error) {
|
|
639
|
+
e.message = errorMsg
|
|
640
|
+
throw e
|
|
641
|
+
}
|
|
642
|
+
throw new Error(errorMsg)
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
558
646
|
async updateEntityManagerReplicaSet({
|
|
559
647
|
userId,
|
|
560
648
|
primary,
|
|
@@ -756,7 +844,6 @@ export class Users extends Base {
|
|
|
756
844
|
'UPDATE_CONTENT_NODE_ENDPOINT_ON_CHAIN',
|
|
757
845
|
UPLOAD_METADATA: 'UPLOAD_METADATA',
|
|
758
846
|
UPDATE_METADATA_ON_CHAIN: 'UPDATE_METADATA_ON_CHAIN',
|
|
759
|
-
UPDATE_USER_ON_CHAIN_OPS: 'UPDATE_USER_ON_CHAIN_OPS',
|
|
760
847
|
ASSOCIATE_USER: 'ASSOCIATE_USER'
|
|
761
848
|
}
|
|
762
849
|
let phase = ''
|
|
@@ -865,6 +952,59 @@ export class Users extends Base {
|
|
|
865
952
|
}
|
|
866
953
|
}
|
|
867
954
|
|
|
955
|
+
/**
|
|
956
|
+
* Storage V2 version of updateAndUploadMetadata. Only posts to chain and not Content Node.
|
|
957
|
+
*/
|
|
958
|
+
async updateMetadataV2({
|
|
959
|
+
newMetadata,
|
|
960
|
+
userId
|
|
961
|
+
}: {
|
|
962
|
+
newMetadata: UserMetadata
|
|
963
|
+
userId: number
|
|
964
|
+
}) {
|
|
965
|
+
this.REQUIRES(Services.DISCOVERY_PROVIDER)
|
|
966
|
+
this.IS_OBJECT(newMetadata)
|
|
967
|
+
|
|
968
|
+
const oldMetadata = this.userStateManager.getCurrentUser()
|
|
969
|
+
if (!oldMetadata) {
|
|
970
|
+
throw new Error('No current user.')
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
newMetadata = this.cleanUserMetadata(newMetadata)
|
|
974
|
+
this._validateUserMetadata(newMetadata)
|
|
975
|
+
|
|
976
|
+
try {
|
|
977
|
+
// Write metadata to chain
|
|
978
|
+
const cid = await Utils.fileHasher.generateMetadataCidV1(newMetadata)
|
|
979
|
+
const { txReceipt } =
|
|
980
|
+
await this.contracts.EntityManagerClient!.manageEntity(
|
|
981
|
+
userId,
|
|
982
|
+
EntityManagerClient.EntityType.USER,
|
|
983
|
+
userId,
|
|
984
|
+
EntityManagerClient.Action.UPDATE,
|
|
985
|
+
JSON.stringify({
|
|
986
|
+
cid: cid.toString(),
|
|
987
|
+
data: newMetadata
|
|
988
|
+
})
|
|
989
|
+
)
|
|
990
|
+
const blockNumber = txReceipt.blockNumber
|
|
991
|
+
|
|
992
|
+
// Update libs instance with new user metadata object
|
|
993
|
+
this.userStateManager.setCurrentUser({ ...oldMetadata, ...newMetadata })
|
|
994
|
+
return {
|
|
995
|
+
blockHash: txReceipt.blockHash,
|
|
996
|
+
blockNumber
|
|
997
|
+
}
|
|
998
|
+
} catch (e) {
|
|
999
|
+
const errorMsg = `updateMetadataV2() error: ${e}`
|
|
1000
|
+
if (e instanceof Error) {
|
|
1001
|
+
e.message = errorMsg
|
|
1002
|
+
throw e
|
|
1003
|
+
}
|
|
1004
|
+
throw new Error(errorMsg)
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
868
1008
|
/**
|
|
869
1009
|
* If a user's creator_node_endpoint is null, assign a replica set.
|
|
870
1010
|
* Used during the sanity check and in uploadImage() in files.js
|
|
@@ -921,12 +1061,12 @@ export class Users extends Base {
|
|
|
921
1061
|
timeoutMs = 60000
|
|
922
1062
|
): Promise<void> {
|
|
923
1063
|
const asyncFn = async () => {
|
|
1064
|
+
const encodedUserId = Utils.encodeHashId(userId)
|
|
924
1065
|
while (true) {
|
|
925
|
-
const encodedUserId = Utils.encodeHashId(userId)
|
|
926
1066
|
let replicaSet
|
|
927
1067
|
try {
|
|
928
1068
|
// If the discovery node has not yet indexed the blocknumber,
|
|
929
|
-
// this method will throw an error
|
|
1069
|
+
// this method will throw an error (which we catch and ignore)
|
|
930
1070
|
// If the user replica set does not exist, it will return an empty object
|
|
931
1071
|
// which should lead to the method throwing an error
|
|
932
1072
|
replicaSet = await this.discoveryProvider.getUserReplicaSet({
|
|
@@ -959,6 +1099,44 @@ export class Users extends Base {
|
|
|
959
1099
|
)
|
|
960
1100
|
}
|
|
961
1101
|
|
|
1102
|
+
async _waitForDiscoveryToIndexUser(
|
|
1103
|
+
userId: number,
|
|
1104
|
+
blockNumber: number,
|
|
1105
|
+
timeoutMs = 60000
|
|
1106
|
+
): Promise<void> {
|
|
1107
|
+
const asyncFn = async () => {
|
|
1108
|
+
while (true) {
|
|
1109
|
+
// Try to get user. Catch+ignore error if the block number isn't yet indexed
|
|
1110
|
+
let user
|
|
1111
|
+
try {
|
|
1112
|
+
user = (
|
|
1113
|
+
await this.discoveryProvider.getUsers(
|
|
1114
|
+
1, // limit
|
|
1115
|
+
0, // offset
|
|
1116
|
+
[userId], // userIds
|
|
1117
|
+
null, // walletAddress
|
|
1118
|
+
null, // handle
|
|
1119
|
+
blockNumber, // minBlockNumber
|
|
1120
|
+
true // includeIncomplete
|
|
1121
|
+
)
|
|
1122
|
+
)?.[0]
|
|
1123
|
+
} catch (err) {}
|
|
1124
|
+
|
|
1125
|
+
// All done (success) if the user was indexed and ID matches
|
|
1126
|
+
if (user?.user_id === userId) {
|
|
1127
|
+
break
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
await Utils.wait(500)
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
await Utils.racePromiseWithTimeout(
|
|
1134
|
+
asyncFn(),
|
|
1135
|
+
timeoutMs,
|
|
1136
|
+
`[User:_waitForDiscoveryToIndexUser()] Timeout error after ${timeoutMs}ms`
|
|
1137
|
+
)
|
|
1138
|
+
}
|
|
1139
|
+
|
|
962
1140
|
_validateUserMetadata(metadata: UserMetadata) {
|
|
963
1141
|
this.OBJECT_HAS_PROPS(metadata, USER_PROPS, USER_REQUIRED_PROPS)
|
|
964
1142
|
}
|
|
@@ -1,12 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"contractName": "Wormhole",
|
|
3
3
|
"abi": [
|
|
4
|
+
{
|
|
5
|
+
"constant": true,
|
|
6
|
+
"inputs": [],
|
|
7
|
+
"name": "DOMAIN_SEPARATOR",
|
|
8
|
+
"outputs": [
|
|
9
|
+
{
|
|
10
|
+
"internalType": "bytes32",
|
|
11
|
+
"name": "",
|
|
12
|
+
"type": "bytes32"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"payable": false,
|
|
16
|
+
"stateMutability": "view",
|
|
17
|
+
"type": "function"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"constant": true,
|
|
21
|
+
"inputs": [],
|
|
22
|
+
"name": "LOCK_ASSETS_TYPEHASH",
|
|
23
|
+
"outputs": [
|
|
24
|
+
{
|
|
25
|
+
"internalType": "bytes32",
|
|
26
|
+
"name": "",
|
|
27
|
+
"type": "bytes32"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"payable": false,
|
|
31
|
+
"stateMutability": "view",
|
|
32
|
+
"type": "function"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"constant": false,
|
|
36
|
+
"inputs": [
|
|
37
|
+
{
|
|
38
|
+
"internalType": "address",
|
|
39
|
+
"name": "_tokenAddress",
|
|
40
|
+
"type": "address"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"internalType": "address",
|
|
44
|
+
"name": "_wormholeAddress",
|
|
45
|
+
"type": "address"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"name": "initialize",
|
|
49
|
+
"outputs": [],
|
|
50
|
+
"payable": false,
|
|
51
|
+
"stateMutability": "nonpayable",
|
|
52
|
+
"type": "function"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"constant": false,
|
|
56
|
+
"inputs": [],
|
|
57
|
+
"name": "initialize",
|
|
58
|
+
"outputs": [],
|
|
59
|
+
"payable": false,
|
|
60
|
+
"stateMutability": "nonpayable",
|
|
61
|
+
"type": "function"
|
|
62
|
+
},
|
|
4
63
|
{
|
|
5
64
|
"constant": false,
|
|
6
65
|
"inputs": [
|
|
7
66
|
{
|
|
8
67
|
"internalType": "address",
|
|
9
|
-
"name": "
|
|
68
|
+
"name": "from",
|
|
10
69
|
"type": "address"
|
|
11
70
|
},
|
|
12
71
|
{
|
|
@@ -14,32 +73,83 @@
|
|
|
14
73
|
"name": "amount",
|
|
15
74
|
"type": "uint256"
|
|
16
75
|
},
|
|
17
|
-
{
|
|
18
|
-
"internalType": "uint16",
|
|
19
|
-
"name": "recipientChain",
|
|
20
|
-
"type": "uint16"
|
|
21
|
-
},
|
|
22
76
|
{
|
|
23
77
|
"internalType": "bytes32",
|
|
24
78
|
"name": "recipient",
|
|
25
79
|
"type": "bytes32"
|
|
26
80
|
},
|
|
81
|
+
{
|
|
82
|
+
"internalType": "uint8",
|
|
83
|
+
"name": "targetChain",
|
|
84
|
+
"type": "uint8"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"internalType": "bool",
|
|
88
|
+
"name": "refundDust",
|
|
89
|
+
"type": "bool"
|
|
90
|
+
},
|
|
27
91
|
{
|
|
28
92
|
"internalType": "uint256",
|
|
29
|
-
"name": "
|
|
93
|
+
"name": "deadline",
|
|
30
94
|
"type": "uint256"
|
|
31
95
|
},
|
|
32
96
|
{
|
|
33
|
-
"internalType": "
|
|
34
|
-
"name": "
|
|
35
|
-
"type": "
|
|
97
|
+
"internalType": "uint8",
|
|
98
|
+
"name": "v",
|
|
99
|
+
"type": "uint8"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"internalType": "bytes32",
|
|
103
|
+
"name": "r",
|
|
104
|
+
"type": "bytes32"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"internalType": "bytes32",
|
|
108
|
+
"name": "s",
|
|
109
|
+
"type": "bytes32"
|
|
36
110
|
}
|
|
37
111
|
],
|
|
38
|
-
"name": "
|
|
112
|
+
"name": "lockAssets",
|
|
39
113
|
"outputs": [],
|
|
40
114
|
"payable": false,
|
|
41
115
|
"stateMutability": "nonpayable",
|
|
42
116
|
"type": "function"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"constant": true,
|
|
120
|
+
"inputs": [
|
|
121
|
+
{
|
|
122
|
+
"internalType": "address",
|
|
123
|
+
"name": "",
|
|
124
|
+
"type": "address"
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
"name": "nonces",
|
|
128
|
+
"outputs": [
|
|
129
|
+
{
|
|
130
|
+
"internalType": "uint32",
|
|
131
|
+
"name": "",
|
|
132
|
+
"type": "uint32"
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"payable": false,
|
|
136
|
+
"stateMutability": "view",
|
|
137
|
+
"type": "function"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"constant": true,
|
|
141
|
+
"inputs": [],
|
|
142
|
+
"name": "token",
|
|
143
|
+
"outputs": [
|
|
144
|
+
{
|
|
145
|
+
"internalType": "address",
|
|
146
|
+
"name": "",
|
|
147
|
+
"type": "address"
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
"payable": false,
|
|
151
|
+
"stateMutability": "view",
|
|
152
|
+
"type": "function"
|
|
43
153
|
}
|
|
44
154
|
]
|
|
45
155
|
}
|
|
@@ -418,6 +418,7 @@ export class CreatorNode {
|
|
|
418
418
|
])
|
|
419
419
|
|
|
420
420
|
// Update metadata to include uploaded CIDs
|
|
421
|
+
updatedMetadata.track_segments = []
|
|
421
422
|
updatedMetadata.track_cid = audioResp.results['320']
|
|
422
423
|
if (updatedMetadata.download?.is_downloadable) {
|
|
423
424
|
updatedMetadata.download.cid = updatedMetadata.track_cid
|
|
@@ -435,6 +436,14 @@ export class CreatorNode {
|
|
|
435
436
|
return await this.uploadFileV2(file, onProgress, 'img_square')
|
|
436
437
|
}
|
|
437
438
|
|
|
439
|
+
async uploadProfilePictureV2(file: File, onProgress: ProgressCB = () => {}) {
|
|
440
|
+
return await this.uploadFileV2(file, onProgress, 'img_square')
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
async uploadCoverPhotoV2(file: File, onProgress: ProgressCB = () => {}) {
|
|
444
|
+
return await this.uploadFileV2(file, onProgress, 'img_backdrop')
|
|
445
|
+
}
|
|
446
|
+
|
|
438
447
|
async uploadFileV2(
|
|
439
448
|
file: File,
|
|
440
449
|
onProgress: ProgressCB,
|
|
@@ -248,7 +248,8 @@ export class DiscoveryProvider {
|
|
|
248
248
|
idsArray: Nullable<number[]>,
|
|
249
249
|
walletAddress?: Nullable<string>,
|
|
250
250
|
handle?: Nullable<string>,
|
|
251
|
-
minBlockNumber?: Nullable<number
|
|
251
|
+
minBlockNumber?: Nullable<number>,
|
|
252
|
+
includeIncomplete?: Nullable<boolean>
|
|
252
253
|
) {
|
|
253
254
|
const req = Requests.getUsers(
|
|
254
255
|
limit,
|
|
@@ -256,7 +257,8 @@ export class DiscoveryProvider {
|
|
|
256
257
|
idsArray,
|
|
257
258
|
walletAddress,
|
|
258
259
|
handle,
|
|
259
|
-
minBlockNumber
|
|
260
|
+
minBlockNumber,
|
|
261
|
+
includeIncomplete
|
|
260
262
|
)
|
|
261
263
|
return await this._makeRequest<Nullable<User[]>>(req)
|
|
262
264
|
}
|
|
@@ -9,7 +9,8 @@ export const getUsers = (
|
|
|
9
9
|
idsArray: Nullable<number[]>,
|
|
10
10
|
walletAddress?: Nullable<string>,
|
|
11
11
|
handle?: Nullable<string>,
|
|
12
|
-
minBlockNumber?: Nullable<number
|
|
12
|
+
minBlockNumber?: Nullable<number>,
|
|
13
|
+
includeIncomplete?: Nullable<boolean>
|
|
13
14
|
) => {
|
|
14
15
|
type QueryParams = {
|
|
15
16
|
limit: number
|
|
@@ -18,6 +19,7 @@ export const getUsers = (
|
|
|
18
19
|
wallet?: string
|
|
19
20
|
min_block_number?: number
|
|
20
21
|
id?: string[]
|
|
22
|
+
include_incomplete?: boolean
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
const queryParams: QueryParams = { limit: limit, offset: offset }
|
|
@@ -36,6 +38,9 @@ export const getUsers = (
|
|
|
36
38
|
}
|
|
37
39
|
queryParams.id = idsArray as unknown as string[]
|
|
38
40
|
}
|
|
41
|
+
if (includeIncomplete != null) {
|
|
42
|
+
queryParams.include_incomplete = includeIncomplete
|
|
43
|
+
}
|
|
39
44
|
|
|
40
45
|
const req = { endpoint: 'users', queryParams }
|
|
41
46
|
|
|
@@ -4,6 +4,27 @@ import { Utils } from '../../utils/utils'
|
|
|
4
4
|
|
|
5
5
|
const { decodeHashId } = Utils
|
|
6
6
|
|
|
7
|
+
const errors = {
|
|
8
|
+
...SubmitAndEvaluateError,
|
|
9
|
+
USERBANK_CREATION: 'USERBANK_CREATION'
|
|
10
|
+
}
|
|
11
|
+
const AAO_ERRORS = new Set<string>([
|
|
12
|
+
errors.AAO_ATTESTATION_REJECTION,
|
|
13
|
+
errors.AAO_ATTESTATION_UNKNOWN_RESPONSE
|
|
14
|
+
])
|
|
15
|
+
// Account for errors from DN aggregation + Solana program
|
|
16
|
+
// CHALLENGE_INCOMPLETE and MISSING_CHALLENGES are already handled in the `submitAndEvaluate` flow -
|
|
17
|
+
// safe to assume those won't work if we see them at this point.
|
|
18
|
+
const NEEDS_RESELECT_ERRORS = new Set<string>([
|
|
19
|
+
errors.INSUFFICIENT_DISCOVERY_NODE_COUNT,
|
|
20
|
+
errors.CHALLENGE_INCOMPLETE,
|
|
21
|
+
errors.MISSING_CHALLENGES
|
|
22
|
+
])
|
|
23
|
+
const ALREADY_COMPLETE_ERRORS = new Set<string>([
|
|
24
|
+
errors.ALREADY_DISBURSED,
|
|
25
|
+
errors.ALREADY_SENT
|
|
26
|
+
])
|
|
27
|
+
|
|
7
28
|
// `BaseRewardsReporter` is intended to be subclassed, and provides
|
|
8
29
|
// "reporting" functionality to RewardsAttester (i.e. posts to Slack if something notable happens)
|
|
9
30
|
class BaseRewardsReporter {
|
|
@@ -698,6 +719,31 @@ export class RewardsAttester {
|
|
|
698
719
|
)}], challengeId: [${challengeId}], quorum size: [${this.quorumSize}]}`
|
|
699
720
|
)
|
|
700
721
|
|
|
722
|
+
const feePayerOverride = this._getFeePayer()
|
|
723
|
+
const { error: userbankCreationError } =
|
|
724
|
+
await this.libs.solanaWeb3Manager.createUserBankIfNeeded(
|
|
725
|
+
feePayerOverride,
|
|
726
|
+
wallet
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
if (userbankCreationError) {
|
|
730
|
+
this.logger.error(
|
|
731
|
+
`Failed to create user bank for user [${decodeHashId(userId)}]`,
|
|
732
|
+
userbankCreationError
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
return {
|
|
736
|
+
challengeId,
|
|
737
|
+
userId,
|
|
738
|
+
specifier,
|
|
739
|
+
amount,
|
|
740
|
+
handle,
|
|
741
|
+
wallet,
|
|
742
|
+
completedBlocknumber,
|
|
743
|
+
error: errors.USERBANK_CREATION
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
701
747
|
const { success, error, aaoErrorCode, phase, nodesToReselect } =
|
|
702
748
|
await this.libs.Rewards.submitAndEvaluate({
|
|
703
749
|
challengeId,
|
|
@@ -711,7 +757,7 @@ export class RewardsAttester {
|
|
|
711
757
|
AAOEndpoint: this.aaoEndpoint,
|
|
712
758
|
endpoints: this.endpoints,
|
|
713
759
|
logger: this.logger,
|
|
714
|
-
feePayerOverride
|
|
760
|
+
feePayerOverride,
|
|
715
761
|
maxAggregationAttempts: this.maxAggregationAttempts
|
|
716
762
|
})
|
|
717
763
|
|
|
@@ -890,26 +936,6 @@ export class RewardsAttester {
|
|
|
890
936
|
shouldReselect: boolean
|
|
891
937
|
failingNodes: string[]
|
|
892
938
|
}> {
|
|
893
|
-
const errors = SubmitAndEvaluateError
|
|
894
|
-
const AAO_ERRORS = new Set([
|
|
895
|
-
errors.HCAPTCHA,
|
|
896
|
-
errors.COGNITO_FLOW,
|
|
897
|
-
errors.AAO_ATTESTATION_REJECTION,
|
|
898
|
-
errors.AAO_ATTESTATION_UNKNOWN_RESPONSE
|
|
899
|
-
])
|
|
900
|
-
// Account for errors from DN aggregation + Solana program
|
|
901
|
-
// CHALLENGE_INCOMPLETE and MISSING_CHALLENGES are already handled in the `submitAndEvaluate` flow -
|
|
902
|
-
// safe to assume those won't work if we see them at this point.
|
|
903
|
-
const NEEDS_RESELECT_ERRORS = new Set([
|
|
904
|
-
errors.INSUFFICIENT_DISCOVERY_NODE_COUNT,
|
|
905
|
-
errors.CHALLENGE_INCOMPLETE,
|
|
906
|
-
errors.MISSING_CHALLENGES
|
|
907
|
-
])
|
|
908
|
-
const ALREADY_COMPLETE_ERRORS = new Set([
|
|
909
|
-
errors.ALREADY_DISBURSED,
|
|
910
|
-
errors.ALREADY_SENT
|
|
911
|
-
])
|
|
912
|
-
|
|
913
939
|
const noRetry: AttestationResult[] = []
|
|
914
940
|
const successful: AttestationResult[] = []
|
|
915
941
|
// Filter our successful responses
|
package/src/utils/fileHasher.ts
CHANGED
|
@@ -14,7 +14,9 @@ import type {
|
|
|
14
14
|
Query,
|
|
15
15
|
KeyQuery
|
|
16
16
|
} from 'interface-store'
|
|
17
|
-
import
|
|
17
|
+
import { CID } from 'multiformats/cid'
|
|
18
|
+
import * as json from 'multiformats/codecs/json'
|
|
19
|
+
import { sha256 } from 'multiformats/hashes/sha2'
|
|
18
20
|
|
|
19
21
|
// Base functionality for only hash logic taken from https://github.com/alanshaw/ipfs-only-hash/blob/master/index.js
|
|
20
22
|
|
|
@@ -154,7 +156,7 @@ export const fileHasher = {
|
|
|
154
156
|
* Custom fn to generate the content-hashing logic
|
|
155
157
|
* @param content a buffer of the content
|
|
156
158
|
* @param options options for importer
|
|
157
|
-
* @returns the CID from content addressing logic
|
|
159
|
+
* @returns the V0 CID from content addressing logic
|
|
158
160
|
*/
|
|
159
161
|
async hashNonImages(
|
|
160
162
|
content: Uint8Array,
|
|
@@ -227,7 +229,7 @@ export const fileHasher = {
|
|
|
227
229
|
},
|
|
228
230
|
|
|
229
231
|
/**
|
|
230
|
-
* Generates CID for a non-image file (track segment, track transcode, metadata)
|
|
232
|
+
* Generates CID V0 (46-char string starting with "Qm") for a non-image file (track segment, track transcode, metadata)
|
|
231
233
|
* @param {Buffer|ReadStream|string} content a single Buffer, a ReadStream, or path to an existing file
|
|
232
234
|
* @param {Object?} logger
|
|
233
235
|
* @returns {string} only hash response cid
|
|
@@ -240,6 +242,19 @@ export const fileHasher = {
|
|
|
240
242
|
return await fileHasher.hashNonImages(buffer)
|
|
241
243
|
},
|
|
242
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Generates CID V1 for a JSON metadata object (NOT the string of the metadata - must be an object).
|
|
247
|
+
* CID<T, 512, SHA_256, 1> represents CID with json codec (512) and sha256 hash using CID V1.
|
|
248
|
+
* Call toString() on the result to get the CID V1 string.
|
|
249
|
+
*/
|
|
250
|
+
async generateMetadataCidV1(
|
|
251
|
+
metadata: {}
|
|
252
|
+
): Promise<CID> {
|
|
253
|
+
const bytes = json.encode(metadata)
|
|
254
|
+
const hash = await sha256.digest(bytes)
|
|
255
|
+
return CID.create(1, json.code, hash)
|
|
256
|
+
},
|
|
257
|
+
|
|
243
258
|
/**
|
|
244
259
|
* Wrapper that generates multihashes for image files
|
|
245
260
|
* @param {Object[]} content an Object[] with the structure [{ path: string, content: buffer }, ...]
|