@audius/sdk 0.0.0

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.
Files changed (278) hide show
  1. package/.eslintrc +38 -0
  2. package/.prettierrc.js +1 -0
  3. package/.python-version +1 -0
  4. package/Dockerfile +15 -0
  5. package/README.md +3 -0
  6. package/babel.config.js +3 -0
  7. package/data-contracts/ABIs/AdminUpgradeabilityProxy.json +132 -0
  8. package/data-contracts/ABIs/BaseAdminUpgradeabilityProxy.json +113 -0
  9. package/data-contracts/ABIs/BaseUpgradeabilityProxy.json +22 -0
  10. package/data-contracts/ABIs/DiscoveryProviderFactory.json +189 -0
  11. package/data-contracts/ABIs/DiscoveryProviderFactoryInterface.json +61 -0
  12. package/data-contracts/ABIs/DiscoveryProviderStorage.json +205 -0
  13. package/data-contracts/ABIs/DiscoveryProviderStorageInterface.json +65 -0
  14. package/data-contracts/ABIs/ECDSA.json +4 -0
  15. package/data-contracts/ABIs/IPLDBlacklistFactory.json +168 -0
  16. package/data-contracts/ABIs/Initializable.json +4 -0
  17. package/data-contracts/ABIs/Migrations.json +67 -0
  18. package/data-contracts/ABIs/OpenZeppelinUpgradesAddress.json +4 -0
  19. package/data-contracts/ABIs/Ownable.json +79 -0
  20. package/data-contracts/ABIs/PlaylistFactory.json +669 -0
  21. package/data-contracts/ABIs/PlaylistFactoryInterface.json +42 -0
  22. package/data-contracts/ABIs/PlaylistStorage.json +250 -0
  23. package/data-contracts/ABIs/PlaylistStorageInterface.json +129 -0
  24. package/data-contracts/ABIs/Proxy.json +10 -0
  25. package/data-contracts/ABIs/Registry.json +240 -0
  26. package/data-contracts/ABIs/RegistryContract.json +102 -0
  27. package/data-contracts/ABIs/RegistryContractInterface.json +28 -0
  28. package/data-contracts/ABIs/RegistryInterface.json +66 -0
  29. package/data-contracts/ABIs/SigningLogic.json +43 -0
  30. package/data-contracts/ABIs/SigningLogicInitializable.json +46 -0
  31. package/data-contracts/ABIs/SocialFeatureFactory.json +460 -0
  32. package/data-contracts/ABIs/SocialFeatureStorage.json +225 -0
  33. package/data-contracts/ABIs/SocialFeatureStorageInterface.json +123 -0
  34. package/data-contracts/ABIs/TestContract.json +135 -0
  35. package/data-contracts/ABIs/TestContractInterface.json +19 -0
  36. package/data-contracts/ABIs/TestContractWithStorage.json +165 -0
  37. package/data-contracts/ABIs/TestContractWithStorageInterface.json +24 -0
  38. package/data-contracts/ABIs/TestStorage.json +144 -0
  39. package/data-contracts/ABIs/TestStorageInterface.json +42 -0
  40. package/data-contracts/ABIs/TestUserReplicaSetManager.json +432 -0
  41. package/data-contracts/ABIs/TrackFactory.json +391 -0
  42. package/data-contracts/ABIs/TrackFactoryInterface.json +73 -0
  43. package/data-contracts/ABIs/TrackStorage.json +223 -0
  44. package/data-contracts/ABIs/TrackStorageInterface.json +121 -0
  45. package/data-contracts/ABIs/UpgradeabilityProxy.json +37 -0
  46. package/data-contracts/ABIs/UserFactory.json +657 -0
  47. package/data-contracts/ABIs/UserFactoryInterface.json +65 -0
  48. package/data-contracts/ABIs/UserLibraryFactory.json +334 -0
  49. package/data-contracts/ABIs/UserReplicaSetManager.json +418 -0
  50. package/data-contracts/ABIs/UserStorage.json +233 -0
  51. package/data-contracts/ABIs/UserStorageInterface.json +93 -0
  52. package/data-contracts/signatureSchemas.ts +1236 -0
  53. package/dist/core.d.ts +446 -0
  54. package/dist/core.js +769 -0
  55. package/dist/core.js.map +1 -0
  56. package/dist/index.d.ts +689 -0
  57. package/dist/index.js +72850 -0
  58. package/dist/index.js.map +1 -0
  59. package/eth-contracts/ABIs/Address.json +4 -0
  60. package/eth-contracts/ABIs/AudiusAdminUpgradeabilityProxy.json +105 -0
  61. package/eth-contracts/ABIs/AudiusClaimDistributor.json +4968 -0
  62. package/eth-contracts/ABIs/AudiusToken.json +724 -0
  63. package/eth-contracts/ABIs/BaseUpgradeabilityProxy.json +23 -0
  64. package/eth-contracts/ABIs/Checkpointing.json +4 -0
  65. package/eth-contracts/ABIs/ClaimsManager.json +539 -0
  66. package/eth-contracts/ABIs/Context.json +11 -0
  67. package/eth-contracts/ABIs/DelegateManager.json +989 -0
  68. package/eth-contracts/ABIs/DelegateManagerV2.json +1049 -0
  69. package/eth-contracts/ABIs/DelegateManagerV2Bad.json +1049 -0
  70. package/eth-contracts/ABIs/ERC20.json +252 -0
  71. package/eth-contracts/ABIs/ERC20Burnable.json +287 -0
  72. package/eth-contracts/ABIs/ERC20Detailed.json +270 -0
  73. package/eth-contracts/ABIs/ERC20Mintable.json +364 -0
  74. package/eth-contracts/ABIs/ERC20Pausable.json +397 -0
  75. package/eth-contracts/ABIs/EthRewardsManager.json +174 -0
  76. package/eth-contracts/ABIs/Governance.json +938 -0
  77. package/eth-contracts/ABIs/GovernanceUpgraded.json +953 -0
  78. package/eth-contracts/ABIs/GovernanceV2.json +938 -0
  79. package/eth-contracts/ABIs/IERC20.json +200 -0
  80. package/eth-contracts/ABIs/Initializable.json +4 -0
  81. package/eth-contracts/ABIs/InitializableV2.json +14 -0
  82. package/eth-contracts/ABIs/Migrations.json +71 -0
  83. package/eth-contracts/ABIs/MinterRole.json +91 -0
  84. package/eth-contracts/ABIs/MockAccount.json +62 -0
  85. package/eth-contracts/ABIs/MockDelegateManager.json +55 -0
  86. package/eth-contracts/ABIs/MockStakingCaller.json +259 -0
  87. package/eth-contracts/ABIs/MockWormhole.json +106 -0
  88. package/eth-contracts/ABIs/OpenZeppelinUpgradesAddress.json +4 -0
  89. package/eth-contracts/ABIs/Ownable.json +93 -0
  90. package/eth-contracts/ABIs/Pausable.json +150 -0
  91. package/eth-contracts/ABIs/PauserRole.json +91 -0
  92. package/eth-contracts/ABIs/Proxy.json +10 -0
  93. package/eth-contracts/ABIs/Registry.json +288 -0
  94. package/eth-contracts/ABIs/Roles.json +4 -0
  95. package/eth-contracts/ABIs/SafeERC20.json +4 -0
  96. package/eth-contracts/ABIs/SafeMath.json +4 -0
  97. package/eth-contracts/ABIs/ServiceProviderFactory.json +1153 -0
  98. package/eth-contracts/ABIs/ServiceTypeManager.json +337 -0
  99. package/eth-contracts/ABIs/Staking.json +555 -0
  100. package/eth-contracts/ABIs/StakingUpgraded.json +570 -0
  101. package/eth-contracts/ABIs/TestContract.json +44 -0
  102. package/eth-contracts/ABIs/TrustedNotifierManager.json +265 -0
  103. package/eth-contracts/ABIs/Uint256Helpers.json +4 -0
  104. package/eth-contracts/ABIs/UpgradeabilityProxy.json +40 -0
  105. package/eth-contracts/ABIs/Wormhole.json +45 -0
  106. package/eth-contracts/ABIs/WormholeClient.json +155 -0
  107. package/examples/file.mp3 +0 -0
  108. package/examples/initAudiusLibs.js +86 -0
  109. package/examples/initializeVersions.js +95 -0
  110. package/examples/pic.jpg +0 -0
  111. package/initScripts/configureLocalDiscProv.js +167 -0
  112. package/initScripts/helpers/claim.js +43 -0
  113. package/initScripts/helpers/distributeTokens.js +24 -0
  114. package/initScripts/helpers/spRegistration.js +138 -0
  115. package/initScripts/helpers/utils.js +34 -0
  116. package/initScripts/helpers/version.js +93 -0
  117. package/initScripts/local.js +617 -0
  118. package/initScripts/mainnet.js +131 -0
  119. package/initScripts/manageProdRelayerWallets.js +191 -0
  120. package/package.json +125 -0
  121. package/rollup.config.js +164 -0
  122. package/scripts/AudiusClaimDistributor.json +4968 -0
  123. package/scripts/Wormhole.json +155 -0
  124. package/scripts/addCIDToIpldBlacklist.js +124 -0
  125. package/scripts/circleci-test.sh +53 -0
  126. package/scripts/communityRewards/transferCommunityRewardsToSolana.js +222 -0
  127. package/scripts/ipfs.sh +58 -0
  128. package/scripts/migrate_contracts.sh +25 -0
  129. package/scripts/reset.sh +65 -0
  130. package/scripts/test.sh +77 -0
  131. package/src/api/account.js +670 -0
  132. package/src/api/base.js +122 -0
  133. package/src/api/file.js +168 -0
  134. package/src/api/playlist.js +328 -0
  135. package/src/api/rewards.d.ts +4 -0
  136. package/src/api/rewards.js +682 -0
  137. package/src/api/serviceProvider.js +154 -0
  138. package/src/api/track.js +604 -0
  139. package/src/api/user.js +888 -0
  140. package/src/api/user.test.js +172 -0
  141. package/src/constants.ts +7 -0
  142. package/src/core.ts +3 -0
  143. package/src/index.js +6 -0
  144. package/src/libs.d.ts +3 -0
  145. package/src/libs.js +619 -0
  146. package/src/sanityChecks/addSecondaries.js +40 -0
  147. package/src/sanityChecks/assignReplicaSetIfNecessary.js +10 -0
  148. package/src/sanityChecks/index.d.ts +9 -0
  149. package/src/sanityChecks/index.js +31 -0
  150. package/src/sanityChecks/isCreator.js +73 -0
  151. package/src/sanityChecks/needsRecoveryEmail.js +20 -0
  152. package/src/sanityChecks/rolloverNodes.js +74 -0
  153. package/src/sanityChecks/sanitizeNodes.js +24 -0
  154. package/src/sanityChecks/syncNodes.js +28 -0
  155. package/src/sdk/constants.ts +10 -0
  156. package/src/sdk/index.ts +1 -0
  157. package/src/sdk/oauth/Oauth.ts +265 -0
  158. package/src/sdk/oauth/index.ts +1 -0
  159. package/src/sdk/sdk.ts +102 -0
  160. package/src/service-selection/ServiceSelection.test.ts +320 -0
  161. package/src/service-selection/ServiceSelection.ts +460 -0
  162. package/src/service-selection/constants.ts +14 -0
  163. package/src/service-selection/index.ts +1 -0
  164. package/src/services/ABIDecoder/AudiusABIDecoder.ts +71 -0
  165. package/src/services/ABIDecoder/index.ts +1 -0
  166. package/src/services/comstock/Comstock.ts +39 -0
  167. package/src/services/comstock/index.ts +1 -0
  168. package/src/services/contracts/ContractClient.ts +227 -0
  169. package/src/services/contracts/GovernedContractClient.ts +53 -0
  170. package/src/services/contracts/ProviderSelection.ts +42 -0
  171. package/src/services/creatorNode/CreatorNode.ts +1065 -0
  172. package/src/services/creatorNode/CreatorNodeSelection.test.ts +997 -0
  173. package/src/services/creatorNode/CreatorNodeSelection.ts +488 -0
  174. package/src/services/creatorNode/constants.ts +10 -0
  175. package/src/services/creatorNode/index.ts +2 -0
  176. package/src/services/dataContracts/AudiusContracts.ts +234 -0
  177. package/src/services/dataContracts/IPLDBlacklistFactoryClient.ts +73 -0
  178. package/src/services/dataContracts/PlaylistFactoryClient.ts +370 -0
  179. package/src/services/dataContracts/RegistryClient.ts +95 -0
  180. package/src/services/dataContracts/SocialFeatureFactoryClient.ts +196 -0
  181. package/src/services/dataContracts/TrackFactoryClient.ts +131 -0
  182. package/src/services/dataContracts/UserFactoryClient.ts +351 -0
  183. package/src/services/dataContracts/UserLibraryFactoryClient.ts +115 -0
  184. package/src/services/dataContracts/UserReplicaSetManagerClient.ts +206 -0
  185. package/src/services/dataContracts/index.ts +1 -0
  186. package/src/services/discoveryProvider/DiscoveryProvider.ts +1168 -0
  187. package/src/services/discoveryProvider/DiscoveryProviderSelection.test.ts +536 -0
  188. package/src/services/discoveryProvider/DiscoveryProviderSelection.ts +383 -0
  189. package/src/services/discoveryProvider/constants.ts +13 -0
  190. package/src/services/discoveryProvider/index.ts +1 -0
  191. package/src/services/discoveryProvider/requests.ts +629 -0
  192. package/src/services/ethContracts/AudiusTokenClient.ts +163 -0
  193. package/src/services/ethContracts/ClaimDistributionClient.ts +45 -0
  194. package/src/services/ethContracts/ClaimsManagerClient.ts +102 -0
  195. package/src/services/ethContracts/DelegateManagerClient.ts +480 -0
  196. package/src/services/ethContracts/EthContracts.ts +359 -0
  197. package/src/services/ethContracts/EthRewardsManagerClient.ts +33 -0
  198. package/src/services/ethContracts/GovernanceClient.ts +451 -0
  199. package/src/services/ethContracts/RegistryClient.ts +33 -0
  200. package/src/services/ethContracts/ServiceProviderFactoryClient.ts +691 -0
  201. package/src/services/ethContracts/ServiceTypeManagerClient.ts +112 -0
  202. package/src/services/ethContracts/StakingProxyClient.ts +97 -0
  203. package/src/services/ethContracts/TrustedNotifierManagerClient.ts +101 -0
  204. package/src/services/ethContracts/WormholeClient.ts +97 -0
  205. package/src/services/ethContracts/index.ts +1 -0
  206. package/src/services/ethWeb3Manager/EthWeb3Manager.ts +239 -0
  207. package/src/services/ethWeb3Manager/index.ts +1 -0
  208. package/src/services/hedgehog/Hedgehog.ts +96 -0
  209. package/src/services/hedgehog/index.ts +1 -0
  210. package/src/services/identity/IdentityService.ts +551 -0
  211. package/src/services/identity/index.ts +1 -0
  212. package/src/services/identity/requests.ts +65 -0
  213. package/src/services/schemaValidator/SchemaValidator.ts +105 -0
  214. package/src/services/schemaValidator/index.ts +1 -0
  215. package/src/services/schemaValidator/schemas/trackSchema.json +267 -0
  216. package/src/services/schemaValidator/schemas/userSchema.json +230 -0
  217. package/src/services/solanaAudiusData/errors.ts +20 -0
  218. package/src/services/solanaAudiusData/index.ts +1189 -0
  219. package/src/services/solanaWeb3Manager/errors.js +101 -0
  220. package/src/services/solanaWeb3Manager/index.d.ts +46 -0
  221. package/src/services/solanaWeb3Manager/index.js +655 -0
  222. package/src/services/solanaWeb3Manager/padBNToUint8Array.ts +7 -0
  223. package/src/services/solanaWeb3Manager/rewards.js +941 -0
  224. package/src/services/solanaWeb3Manager/rewardsAttester.ts +1093 -0
  225. package/src/services/solanaWeb3Manager/tokenAccount.js +149 -0
  226. package/src/services/solanaWeb3Manager/transactionHandler.js +345 -0
  227. package/src/services/solanaWeb3Manager/transfer.js +272 -0
  228. package/src/services/solanaWeb3Manager/userBank.js +160 -0
  229. package/src/services/solanaWeb3Manager/utils.d.ts +31 -0
  230. package/src/services/solanaWeb3Manager/utils.js +163 -0
  231. package/src/services/solanaWeb3Manager/wAudio.js +28 -0
  232. package/src/services/solanaWeb3Manager/wAudio.test.js +30 -0
  233. package/src/services/web3Manager/Web3Config.ts +14 -0
  234. package/src/services/web3Manager/Web3Manager.ts +360 -0
  235. package/src/services/web3Manager/XMLHttpRequest.ts +11 -0
  236. package/src/services/web3Manager/index.ts +2 -0
  237. package/src/services/wormhole/index.js +424 -0
  238. package/src/types.ts +8 -0
  239. package/src/userStateManager.ts +53 -0
  240. package/src/utils/apiSigning.ts +51 -0
  241. package/src/utils/captcha.ts +97 -0
  242. package/src/utils/estimateGas.ts +64 -0
  243. package/src/utils/fileHasher.ts +278 -0
  244. package/src/utils/importContractABI.d.ts +9 -0
  245. package/src/utils/importContractABI.js +19 -0
  246. package/src/utils/index.ts +11 -0
  247. package/src/utils/multiProvider.ts +72 -0
  248. package/src/utils/network.test.ts +127 -0
  249. package/src/utils/network.ts +308 -0
  250. package/src/utils/promiseFight.test.ts +87 -0
  251. package/src/utils/promiseFight.ts +36 -0
  252. package/src/utils/signatures.ts +139 -0
  253. package/src/utils/types.ts +34 -0
  254. package/src/utils/utils.test.ts +36 -0
  255. package/src/utils/utils.ts +235 -0
  256. package/src/utils/uuid.ts +14 -0
  257. package/src/web3.d.ts +9 -0
  258. package/src/web3.js +8 -0
  259. package/tests/assets/static_image.png +0 -0
  260. package/tests/assets/static_text.txt +1 -0
  261. package/tests/audiusTokenClientTest.js +37 -0
  262. package/tests/creatorNodeTest.js +19 -0
  263. package/tests/fileHasherTest.js +125 -0
  264. package/tests/governanceTest.js +382 -0
  265. package/tests/helpers.js +105 -0
  266. package/tests/index.js +14 -0
  267. package/tests/playlistClientTest.js +157 -0
  268. package/tests/providerSelectionTest.js +241 -0
  269. package/tests/registryClientTest.js +19 -0
  270. package/tests/rewardsAttesterTest.js +373 -0
  271. package/tests/serviceTypeManagerClientTest.js +33 -0
  272. package/tests/socialFeatureClientTest.js +79 -0
  273. package/tests/stakingTest.js +302 -0
  274. package/tests/trackClientTest.js +86 -0
  275. package/tests/userClientTest.js +121 -0
  276. package/tsconfig.json +10 -0
  277. package/types/@audius-hedgehog/index.d.ts +39 -0
  278. package/types/abi-decoder/index.d.ts +41 -0
@@ -0,0 +1,241 @@
1
+ const assert = require('assert')
2
+ const sinon = require('sinon')
3
+
4
+ const { ContractClient } = require('../src/services/contracts/ContractClient')
5
+ const { Web3Manager } = require('../src/services/web3Manager')
6
+ const { EthWeb3Manager } = require('../src/services/ethWeb3Manager')
7
+
8
+ const CONTRACT_INIT_MAX_ATTEMPTS = 5
9
+
10
+ let contractClient
11
+
12
+ describe('Testing ContractClient class with ProviderSelection', () => {
13
+ afterEach(async () => {
14
+ // Reset stub
15
+ sinon.restore()
16
+ })
17
+
18
+ /**
19
+ * Given: audius gateway is healthy
20
+ * When: we do contract logic
21
+ * Should: do not use provider selection logic and use initially set audius gateway
22
+ */
23
+ it('should use initial audius gateway if healthy', async () => {
24
+ contractClient = createContractClientWithInternalWeb3()
25
+ sinon
26
+ .stub(contractClient.web3Manager.web3.eth, 'Contract')
27
+ .callsFake((arg1, arg2) => {
28
+ return arg1
29
+ })
30
+ const initWithProviderSelectionSpy = sinon.spy(contractClient, 'init')
31
+ const consoleSpy = sinon.spy(console, 'error')
32
+
33
+ await contractClient.init()
34
+
35
+ assert.strictEqual(
36
+ contractClient.web3Manager.getWeb3().currentProvider.host,
37
+ 'https://audius.poa.network'
38
+ )
39
+ assert(initWithProviderSelectionSpy.calledOnce)
40
+ assert(consoleSpy.notCalled)
41
+ })
42
+
43
+ /**
44
+ * Given: both gatetways are unhealthy
45
+ * When: we do contract logic
46
+ * Should: try both gateways and then log error
47
+ *
48
+ * @notice when web3 is set to a new object, the second call will throw a different error
49
+ * that is acceptable as we don't care about what the error is
50
+ */
51
+ it('should log error if both audius gateway and public gateway are unhealthy', async () => {
52
+ contractClient = createContractClientWithInternalWeb3()
53
+ sinon
54
+ .stub(contractClient.web3Manager.web3.eth, 'Contract')
55
+ .callsFake((arg1, arg2) => {
56
+ throw new Error('Bad provider')
57
+ })
58
+ const initWithProviderSelectionSpy = sinon.spy(contractClient, 'init')
59
+ const consoleSpy = sinon.spy(console, 'error')
60
+
61
+ await contractClient.init()
62
+
63
+ assert(
64
+ initWithProviderSelectionSpy.callCount === CONTRACT_INIT_MAX_ATTEMPTS
65
+ )
66
+ assert(consoleSpy.callCount === CONTRACT_INIT_MAX_ATTEMPTS)
67
+ })
68
+
69
+ /**
70
+ * Given: contractClient.web3Manager is instanceof ethWeb3Manager
71
+ * When: contract logic passes
72
+ * Should: pass on first try and use initially set gateway
73
+ */
74
+ it('should use initial gateway url if web3Manager is instanceof ethWeb3Manager and contract logic passes', async () => {
75
+ contractClient = createContractClientWithEthWeb3Manager()
76
+ sinon
77
+ .stub(contractClient.web3Manager.web3.eth, 'Contract')
78
+ .callsFake((arg1, arg2) => {
79
+ return arg1
80
+ })
81
+ const initWithProviderSelectionSpy = sinon.spy(contractClient, 'init')
82
+ const consoleSpy = sinon.spy(console, 'error')
83
+
84
+ await contractClient.init()
85
+
86
+ assert.strictEqual(
87
+ contractClient.web3Manager.getWeb3().currentProvider.host,
88
+ 'https://eth.network'
89
+ )
90
+ assert(initWithProviderSelectionSpy.calledOnce)
91
+ assert(consoleSpy.notCalled)
92
+ })
93
+
94
+ /**
95
+ * Given: contractClient.web3Manager is instanceof ethWeb3Manager
96
+ * When: contract logic fails
97
+ * Should: do not do retry logic and log error
98
+ */
99
+ it('should log error if web3Manager is instanceof ethWeb3Manager and contract logic fails', async () => {
100
+ contractClient = createContractClientWithEthWeb3Manager()
101
+ sinon
102
+ .stub(contractClient.web3Manager.web3.eth, 'Contract')
103
+ .callsFake((arg1, arg2) => {
104
+ throw new Error('Bad provider')
105
+ })
106
+ const initWithProviderSelectionSpy = sinon.spy(contractClient, 'init')
107
+ const consoleSpy = sinon.spy(console, 'error')
108
+
109
+ await contractClient.init()
110
+
111
+ assert.strictEqual(
112
+ contractClient.web3Manager.getWeb3().currentProvider.host,
113
+ 'https://eth.network'
114
+ )
115
+ assert(
116
+ initWithProviderSelectionSpy.callCount === CONTRACT_INIT_MAX_ATTEMPTS
117
+ )
118
+ assert(consoleSpy.callCount === CONTRACT_INIT_MAX_ATTEMPTS)
119
+ })
120
+
121
+ /**
122
+ * Given: we are using an external web3
123
+ * When: contract logic passes
124
+ * Should: pass on first try and use initially set gateway
125
+ */
126
+ it('should use initial gateway url if useExternalWeb3 is true and contract logic passes', async () => {
127
+ contractClient = createContractClientWithExternalWeb3()
128
+ sinon
129
+ .stub(contractClient.web3Manager.web3.eth, 'Contract')
130
+ .callsFake((arg1, arg2) => {
131
+ return arg1
132
+ })
133
+ const initWithProviderSelectionSpy = sinon.spy(contractClient, 'init')
134
+ const consoleSpy = sinon.spy(console, 'error')
135
+
136
+ await contractClient.init()
137
+
138
+ assert.strictEqual(
139
+ contractClient.web3Manager.getWeb3().currentProvider.host,
140
+ 'https://audius.poa.network'
141
+ )
142
+ assert(initWithProviderSelectionSpy.calledOnce)
143
+ assert(consoleSpy.notCalled)
144
+ })
145
+
146
+ /**
147
+ * Given: we are using an external web3
148
+ * When: contract logic fails
149
+ * Should: do not do retry logic and log error
150
+ */
151
+ it('should log error if useExternalWeb3 is true and contract logic fails', async () => {
152
+ contractClient = createContractClientWithExternalWeb3()
153
+ sinon
154
+ .stub(contractClient.web3Manager.web3.eth, 'Contract')
155
+ .callsFake((arg1, arg2) => {
156
+ throw new Error('Bad provider')
157
+ })
158
+ const initWithProviderSelectionSpy = sinon.spy(contractClient, 'init')
159
+ const consoleSpy = sinon.spy(console, 'error')
160
+
161
+ await contractClient.init()
162
+
163
+ assert(
164
+ initWithProviderSelectionSpy.callCount === CONTRACT_INIT_MAX_ATTEMPTS
165
+ )
166
+ assert(consoleSpy.callCount === CONTRACT_INIT_MAX_ATTEMPTS)
167
+ })
168
+ })
169
+ // Helper stub and functions for providerSelectionTest
170
+
171
+ // Available providers
172
+ const gateways = ['https://audius.poa.network', 'https://public.poa.network']
173
+
174
+ // Creates barebones web3 object
175
+ function createWeb3Obj(host) {
176
+ return {
177
+ currentProvider: {
178
+ host
179
+ },
180
+ eth: {
181
+ Contract: () => {}
182
+ }
183
+ }
184
+ }
185
+
186
+ // Helper functions to create ContractClient instances with the appropriate properties
187
+
188
+ function createContractClient(web3Manager) {
189
+ const getRegistryAddressFn = () => {
190
+ return '0xaaaaaaaaaaaaaaaaaaa'
191
+ }
192
+
193
+ if (web3Manager instanceof Web3Manager) {
194
+ sinon.stub(web3Manager, 'provider').callsFake((arg1, arg2) => {
195
+ return arg1
196
+ })
197
+ }
198
+
199
+ return new ContractClient(
200
+ web3Manager,
201
+ 'contractABI',
202
+ 'contractRegistryKey',
203
+ getRegistryAddressFn
204
+ )
205
+ }
206
+
207
+ function createContractClientWithInternalWeb3() {
208
+ const web3Config = {
209
+ useExternalWeb3: false,
210
+ internalWeb3Config: {
211
+ web3ProviderEndpoints: gateways
212
+ }
213
+ }
214
+ const web3Manager = new Web3Manager()
215
+ web3Manager.web3 = createWeb3Obj('https://audius.poa.network')
216
+ web3Manager.web3Config = web3Config
217
+ return createContractClient(web3Manager)
218
+ }
219
+
220
+ function createContractClientWithExternalWeb3() {
221
+ const web3Config = {
222
+ useExternalWeb3: true,
223
+ internalWeb3Config: {
224
+ web3ProviderEndpoints: gateways
225
+ }
226
+ }
227
+ const web3Manager = new Web3Manager()
228
+ web3Manager.web3 = createWeb3Obj('https://audius.poa.network')
229
+ web3Manager.web3Config = web3Config
230
+ return createContractClient(web3Manager)
231
+ }
232
+
233
+ function createContractClientWithEthWeb3Manager() {
234
+ const web3Config = {
235
+ providers: ['https://audius.eth.network'],
236
+ ownerWallet: '0xwallet'
237
+ }
238
+ const ethWeb3Manager = new EthWeb3Manager(web3Config)
239
+ ethWeb3Manager.web3 = createWeb3Obj('https://eth.network')
240
+ return createContractClient(ethWeb3Manager)
241
+ }
@@ -0,0 +1,19 @@
1
+ const assert = require('assert')
2
+ let helpers = require('./helpers')
3
+
4
+ let audiusInstance = helpers.audiusInstance
5
+
6
+ before(async function () {
7
+ await audiusInstance.init()
8
+ })
9
+
10
+ it('should call getContract for creatorStorage key', async function () {
11
+ let address = await audiusInstance.contracts.RegistryClient.getContract('creatorStorage')
12
+ assert.notStrictEqual(address, helpers.constants['0x0'])
13
+ })
14
+
15
+ it('should call getContract for nonexistent key', async function () {
16
+ let address = await audiusInstance.contracts.RegistryClient.getContract('nonexistent')
17
+ // not helpers 0x0 because it's not a bytes32 zero value, different number of 0's
18
+ assert.strictEqual(address, '0x0000000000000000000000000000000000000000')
19
+ })
@@ -0,0 +1,373 @@
1
+ const assert = require('assert')
2
+ const sinon = require('sinon')
3
+ const {
4
+ AttestationPhases,
5
+ SubmitAndEvaluateError
6
+ } = require('../src/api/rewards')
7
+ const {
8
+ RewardsAttester,
9
+ AttestationDelayCalculator
10
+ } = require('../src/services/solanaWeb3Manager/rewardsAttester')
11
+ const { Utils } = require('../src/utils')
12
+ const { encodeHashId } = Utils
13
+
14
+ function MockLibs(getSlot = () => 100, getBlockNumber = () => 100) {
15
+ this.getSlot = getSlot
16
+ this.getBlockNumber = getBlockNumber
17
+ this.solanaWeb3Manager = {
18
+ getSlot: () => this.getSlot(),
19
+ hasBalance: ({ publicKey }) => true
20
+ }
21
+ this.web3Manager = {
22
+ getWeb3: () => ({
23
+ eth: {
24
+ getBlockNumber: () => this.getBlockNumber()
25
+ }
26
+ })
27
+ }
28
+ this.Rewards = {
29
+ submitAndEvaluate: (args) => {},
30
+ getUndisbursedChallenges: (args) => {},
31
+ ServiceProvider: {
32
+ getUniquelyOwnedDiscoveryNodes: (quorumSize, nodes) => {
33
+ return nodes.slice(0, quorumSize)
34
+ }
35
+ }
36
+ }
37
+ this.discoveryProvider = {
38
+ serviceSelector: {
39
+ findAll: ({ whitelist }) => {
40
+ return whitelist
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ let calc = null
47
+
48
+ describe('Delay calculator tests', () => {
49
+ afterEach(async () => {
50
+ calc.stop()
51
+ })
52
+
53
+ it('Should get Slot and block threshold on fresh start', async () => {
54
+ calc = new AttestationDelayCalculator({
55
+ libs: new MockLibs(
56
+ () => 100,
57
+ () => 100
58
+ ),
59
+ runBehindSec: 5,
60
+ allowedStalenessSec: 1
61
+ })
62
+ await calc.start()
63
+ const slotThreshold = await calc.getSolanaSlotThreshold()
64
+ // Should be 90: 100 - 5 / 0.5 block/sec
65
+ assert.strictEqual(slotThreshold, 90)
66
+
67
+ const blockThreshold = await calc.getPOABlockThreshold()
68
+ // Should be 99: 100 - 5 / 5
69
+ assert.strictEqual(blockThreshold, 99)
70
+ })
71
+
72
+ it('Should cache slot and block values', async () => {
73
+ const libs = new MockLibs(
74
+ () => 100,
75
+ () => 100
76
+ )
77
+ calc = new AttestationDelayCalculator({
78
+ libs,
79
+ runBehindSec: 5,
80
+ allowedStalenessSec: 1
81
+ })
82
+ await calc.start()
83
+ await calc.getSolanaSlotThreshold()
84
+ await calc.getPOABlockThreshold()
85
+
86
+ // Test cached values
87
+ libs.getSlot = () => 110
88
+ libs.getBlockNumber = () => 110
89
+ const slotThreshold = await calc.getSolanaSlotThreshold()
90
+ assert.strictEqual(slotThreshold, 90)
91
+ const blockThreshold = await calc.getPOABlockThreshold()
92
+ assert.strictEqual(blockThreshold, 99)
93
+ })
94
+
95
+ it('Should get new values after the cache expires', async () => {
96
+ const libs = new MockLibs(
97
+ () => 100,
98
+ () => 100
99
+ )
100
+ calc = new AttestationDelayCalculator({
101
+ libs,
102
+ runBehindSec: 5,
103
+ allowedStalenessSec: 1
104
+ })
105
+ await calc.start()
106
+ await calc.getSolanaSlotThreshold()
107
+ await calc.getPOABlockThreshold()
108
+
109
+ // Test cached values
110
+ await new Promise((res) => setTimeout(res, 1100))
111
+ libs.getSlot = () => 110
112
+ libs.getBlockNumber = () => 110
113
+ const slotThreshold = await calc.getSolanaSlotThreshold()
114
+ assert.strictEqual(slotThreshold, 100)
115
+ const blockThreshold = await calc.getPOABlockThreshold()
116
+ assert.strictEqual(blockThreshold, 109)
117
+ })
118
+
119
+ it('Should update the solana slot properly', async () => {
120
+ const solSlot = {
121
+ last: 100
122
+ }
123
+ // new slots every 250ms
124
+ const i = setInterval(() => {
125
+ solSlot.last += 1
126
+ }, 250)
127
+
128
+ const libs = new MockLibs(
129
+ () => solSlot.last,
130
+ () => 100
131
+ )
132
+
133
+ calc = new AttestationDelayCalculator({
134
+ libs,
135
+ runBehindSec: 5,
136
+ allowedStalenessSec: 1,
137
+ solanaPollingInterval: 0.5
138
+ })
139
+ calc.start()
140
+ const slotThreshold1 = await calc.getSolanaSlotThreshold()
141
+ // Initially this should be 0.5sec/slot
142
+ assert.strictEqual(slotThreshold1, 90)
143
+
144
+ // Wait for staleness interval
145
+ await new Promise((res) => setTimeout(res, 1100))
146
+ const slotThreshold2 = await calc.getSolanaSlotThreshold()
147
+ // Current slot should be 104, and there should be 4 slots/sec,
148
+ // so 5 sec lag behind = 104 - 5 * 4 = 84
149
+ assert.strictEqual(slotThreshold2, 84)
150
+
151
+ clearInterval(i)
152
+ })
153
+ })
154
+
155
+ describe('Rewards Attester Tests', () => {
156
+ afterEach(async () => {
157
+ sinon.restore()
158
+ })
159
+
160
+ it('Should handle happy path attestation loop', async () => {
161
+ const libs = new MockLibs()
162
+
163
+ const attester = new RewardsAttester({
164
+ libs,
165
+ startingBlock: 0,
166
+ offset: 0,
167
+ parallelization: 2,
168
+ quorumSize: 2,
169
+ aaoEndpoint: 'https://fakeaao.co',
170
+ aaoAddress: '0xFakeOracle',
171
+ challengeIdsDenyList: [],
172
+ endpoints: ['https://dn1.co', 'https://dn2.co', 'https://dn3.co'],
173
+ isSolanaChallenge: () => false,
174
+ feePayerOverride: 'test feepayer override'
175
+ })
176
+
177
+ const rewardsMock = sinon.mock(libs.Rewards)
178
+
179
+ rewardsMock
180
+ .expects('getUndisbursedChallenges')
181
+ .exactly(3)
182
+ .onFirstCall()
183
+ .returns(withSuccess([1, 2].map((i) => makeChallenge(i, i))))
184
+ .onSecondCall()
185
+ .returns(withSuccess([3, 4].map((i) => makeChallenge(i, i))))
186
+ .onThirdCall()
187
+ .callsFake(() => {
188
+ attester.stop()
189
+ return {
190
+ success: []
191
+ }
192
+ })
193
+
194
+ rewardsMock
195
+ .expects('submitAndEvaluate')
196
+ .exactly(4)
197
+ .returns({ success: true })
198
+
199
+ await attester.start()
200
+ assert.equal(attester.startingBlock, 3)
201
+ assert.equal(attester.offset, 0)
202
+ rewardsMock.verify()
203
+ })
204
+
205
+ it('Sets offset correctly for unretryable errors with same starting block', async () => {
206
+ // This tests that we *add* offsets correctly if each challenge we return has the same starting block.
207
+ // For this test, fetch challenges in batches of 2, and the first 4 all share the same completed block
208
+ // and are unretryable, so the offset should be 4 by the end
209
+ const libs = new MockLibs()
210
+ const rewardsStub = sinon.stub(libs.Rewards)
211
+
212
+ const attester = new RewardsAttester({
213
+ libs,
214
+ startingBlock: 0,
215
+ offset: 0,
216
+ parallelization: 2,
217
+ quorumSize: 2,
218
+ aaoEndpoint: 'https://fakeaao.co',
219
+ aaoAddress: '0xFakeOracle',
220
+ challengeIdsDenyList: [],
221
+ endpoints: ['https://dn1.co', 'https://dn2.co', 'https://dn3.co'],
222
+ isSolanaChallenge: () => false,
223
+ feePayerOverride: 'test feepayer override'
224
+ })
225
+
226
+ const [attesterPromise, resolve] = makeAttesterPromise()
227
+
228
+ rewardsStub.getUndisbursedChallenges
229
+ .onFirstCall()
230
+ .returns(withSuccess([0, 1].map((i) => makeChallenge(i, 1))))
231
+ .onSecondCall()
232
+ .returns(withSuccess([2, 3].map((i) => makeChallenge(i, 1))))
233
+ .onThirdCall()
234
+ .callsFake(() => {
235
+ attester.stop()
236
+ resolve()
237
+ return withSuccess([])
238
+ })
239
+
240
+ // Entries 0-3 should return rejection (no retry)
241
+ rewardsStub.submitAndEvaluate
242
+ .withArgs(sinon.match({ specifier: sinon.match.in([0, 1, 2, 3]) }))
243
+ .returns({
244
+ success: false,
245
+ error: SubmitAndEvaluateError.AAO_ATTESTATION_REJECTION,
246
+ phase: AttestationPhases.AGGREGATE_ATTESTATIONS
247
+ })
248
+
249
+ await attester.start()
250
+ await attesterPromise
251
+
252
+ assert.equal(attester.startingBlock, 0)
253
+ assert.equal(attester.offset, 4)
254
+ })
255
+
256
+ it('Sets offset correctly for unretryable errors with different starting block', async () => {
257
+ // If we get some unretryable errors with a different starting block,
258
+ // we should *reset* the offset instead of accumulating it.
259
+
260
+ const libs = new MockLibs()
261
+ const rewardsStub = sinon.stub(libs.Rewards)
262
+
263
+ const attester = new RewardsAttester({
264
+ libs,
265
+ startingBlock: 0,
266
+ offset: 0,
267
+ parallelization: 2,
268
+ quorumSize: 2,
269
+ aaoEndpoint: 'https://fakeaao.co',
270
+ aaoAddress: '0xFakeOracle',
271
+ challengeIdsDenyList: [],
272
+ endpoints: ['https://dn1.co', 'https://dn2.co', 'https://dn3.co'],
273
+ isSolanaChallenge: () => false,
274
+ feePayerOverride: 'test feepayer override'
275
+ })
276
+
277
+ const [attesterPromise, resolve] = makeAttesterPromise()
278
+
279
+ rewardsStub.getUndisbursedChallenges
280
+ .onFirstCall()
281
+ .returns(withSuccess([0, 1].map((i) => makeChallenge(i, 1))))
282
+ .onSecondCall()
283
+ .returns(withSuccess([2, 3].map((i) => makeChallenge(i, 2))))
284
+ .onThirdCall()
285
+ .callsFake(() => {
286
+ attester.stop()
287
+ resolve()
288
+ return withSuccess([])
289
+ })
290
+
291
+ // Entries 0-3 should return rejection (no retry)
292
+ rewardsStub.submitAndEvaluate
293
+ .withArgs(sinon.match({ specifier: sinon.match.in([0, 1, 2, 3]) }))
294
+ .returns({
295
+ success: false,
296
+ error: SubmitAndEvaluateError.AAO_ATTESTATION_REJECTION,
297
+ phase: AttestationPhases.AGGREGATE_ATTESTATIONS
298
+ })
299
+
300
+ await attester.start()
301
+ await attesterPromise
302
+
303
+ assert.equal(attester.startingBlock, 1)
304
+ assert.equal(attester.offset, 2)
305
+ })
306
+
307
+ it('Handles errors in processChallenges after retrying', async () => {
308
+ // processChallenges needs to return an error after it retries and fails,
309
+ // so that clients can act upon the error
310
+
311
+ const libs = new MockLibs()
312
+ const rewardsMock = sinon.mock(libs.Rewards)
313
+
314
+ const attester = new RewardsAttester({
315
+ libs,
316
+ startingBlock: 0,
317
+ offset: 0,
318
+ parallelization: 2,
319
+ quorumSize: 2,
320
+ aaoEndpoint: 'https://fakeaao.co',
321
+ aaoAddress: '0xFakeOracle',
322
+ challengeIdsDenyList: [],
323
+ endpoints: ['https://dn1.co', 'https://dn2.co', 'https://dn3.co'],
324
+ isSolanaChallenge: () => false,
325
+ feePayerOverride: 'test feepayer override',
326
+ maxCooldownMsec: 100
327
+ })
328
+
329
+ // Have it always return a retryable error
330
+ rewardsMock
331
+ .expects("submitAndEvaluate")
332
+ .exactly(5)
333
+ .returns({
334
+ success: false,
335
+ error: SubmitAndEvaluateError.CHALLENGE_INCOMPLETE,
336
+ phase: AttestationPhases.AGGREGATE_ATTESTATIONS
337
+ })
338
+
339
+ const { errors } = await attester.processChallenges([
340
+ {
341
+ challengeId: 'profile-completion',
342
+ userId: encodeHashId(1),
343
+ specifier: '1',
344
+ amount: '1',
345
+ completedBlocknumber: 1,
346
+ handle: 'user_1',
347
+ wallet: '0x1'
348
+ }
349
+ ])
350
+
351
+ assert.equal(errors?.length, 1)
352
+ })
353
+ })
354
+
355
+ const makeAttesterPromise = () => {
356
+ let res = null
357
+ const promise = new Promise((resolve) => (res = resolve))
358
+ return [promise, res]
359
+ }
360
+
361
+ const withSuccess = (objs) => ({
362
+ success: objs
363
+ })
364
+
365
+ const makeChallenge = (index, completedBlocknumber) => ({
366
+ challenge_id: 'profile-completion',
367
+ user_id: encodeHashId(index),
368
+ specifier: index,
369
+ amount: '1',
370
+ completed_blocknumber: completedBlocknumber,
371
+ handle: `user_ ${index}`,
372
+ wallet: `0x${index}`
373
+ })
@@ -0,0 +1,33 @@
1
+ const assert = require('assert')
2
+ const helpers = require('./helpers')
3
+
4
+ const latestVersionStr = '0.1.0'
5
+
6
+ const audius0 = helpers.audiusInstance
7
+
8
+ let serviceTypeList
9
+ let ownerWallet
10
+ let accounts
11
+
12
+ before(async function () {
13
+ await audius0.init()
14
+ ownerWallet = audius0.ethWeb3Manager.getWalletAddress()
15
+ accounts = await audius0.ethWeb3Manager.getWeb3().eth.getAccounts()
16
+ serviceTypeList = await audius0.ethContracts.ServiceTypeManagerClient.getValidServiceTypes()
17
+ })
18
+
19
+ it('register service versions', async function () {
20
+ for (const serviceType of serviceTypeList) {
21
+ await audius0.ethContracts.ServiceTypeManagerClient.setServiceVersion(
22
+ serviceType,
23
+ latestVersionStr
24
+ )
25
+ }
26
+ })
27
+
28
+ it('query service versions', async function () {
29
+ for (const serviceType of serviceTypeList) {
30
+ let currentVersion = await audius0.ethContracts.ServiceTypeManagerClient.getCurrentVersion(serviceType)
31
+ assert(currentVersion === latestVersionStr, 'Expect latest version')
32
+ }
33
+ })