@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,272 @@
1
+ const {
2
+ SystemProgram,
3
+ PublicKey,
4
+ Secp256k1Program,
5
+ SYSVAR_INSTRUCTIONS_PUBKEY,
6
+ SYSVAR_RENT_PUBKEY,
7
+ TransactionInstruction
8
+ } = require('@solana/web3.js')
9
+ const borsh = require('borsh')
10
+ const SolanaUtils = require('./utils')
11
+ const secp256k1 = require('secp256k1')
12
+ const { ClaimableProgramError } = require('./errors')
13
+
14
+ const encoder = new TextEncoder()
15
+
16
+ const TRANSFER_NONCE_PREFIX = 'N_'
17
+
18
+ /**
19
+ * Derives the 'transfer nonce account' - the account which contains the nonce for transfers
20
+ * and is used to prevent replay attacks
21
+ *
22
+ * @param {string} ethAddress
23
+ * @param {PublicKey} rewardProgramId
24
+ * @param {PublicKey} rewardManager
25
+ * @returns {Promise<PublicKey>}
26
+ */
27
+ const deriveTransferNonceAccount = async ({
28
+ ethAddress,
29
+ mintKey,
30
+ claimableTokenProgramKey
31
+ }) => {
32
+ const ethAddressArr = SolanaUtils.ethAddressToArray(ethAddress)
33
+ const seed = Uint8Array.from([
34
+ ...encoder.encode(TRANSFER_NONCE_PREFIX),
35
+ ...ethAddressArr
36
+ ])
37
+
38
+ const res = await SolanaUtils.findProgramAddressWithAuthority(
39
+ claimableTokenProgramKey,
40
+ mintKey,
41
+ seed
42
+ )
43
+ return res[1]
44
+ }
45
+
46
+ class NonceAccount {
47
+ constructor ({
48
+ version,
49
+ nonce
50
+ }) {
51
+ this.version = version
52
+ this.nonce = nonce
53
+ }
54
+ }
55
+
56
+ const NonceAccountSchema = new Map([
57
+ [
58
+ NonceAccount,
59
+ {
60
+ kind: 'struct',
61
+ fields: [
62
+ ['version', 'u8'],
63
+ ['nonce', 'u64']
64
+ ]
65
+ }
66
+ ]
67
+ ])
68
+
69
+ /**
70
+ * Retrieves the nonce account for transfers, if non-existant it returns 0
71
+ * @param {object} params
72
+ * @param {object} params.connection Solana web3 connection
73
+ * @param {string} params.ethAddress Eth Address
74
+ * @param {PublicKey} params.mintKey Public key of the minted spl token
75
+ * @param {PublicKey} params.claimableTokenProgramKey Program public key
76
+ */
77
+ async function getAccountNonce ({
78
+ connection,
79
+ ethAddress,
80
+ mintKey,
81
+ claimableTokenProgramKey
82
+ }) {
83
+ let nonce = 0
84
+ const transferNonceAccount = await deriveTransferNonceAccount({
85
+ ethAddress,
86
+ mintKey,
87
+ claimableTokenProgramKey
88
+ })
89
+ const accInfo = await connection.getAccountInfoAndContext(transferNonceAccount)
90
+ if (accInfo.value) {
91
+ const nonceAccount = borsh.deserialize(NonceAccountSchema, NonceAccount, accInfo.value.data)
92
+ nonce = nonceAccount.nonce
93
+ }
94
+ return {
95
+ accountNonce: transferNonceAccount,
96
+ nonce
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Transfer wAUDIO between wallets on solana
102
+ */
103
+ class TransferInstructionData {
104
+ constructor ({
105
+ targetPubKey,
106
+ amount,
107
+ nonce
108
+ }) {
109
+ this.target_pubkey = targetPubKey
110
+ this.amount = amount
111
+ this.nonce = nonce
112
+ }
113
+ }
114
+
115
+ const transferInstructionDataSchema = new Map([
116
+ [
117
+ TransferInstructionData,
118
+ {
119
+ kind: 'struct',
120
+ fields: [
121
+ ['target_pubkey', [32]], // type pubkey of length 32 bytes
122
+ ['amount', 'u64'],
123
+ ['nonce', 'u64']
124
+ ]
125
+ }
126
+ ]
127
+ ])
128
+
129
+ /**
130
+ * transferWAudioBalance transfers wrapped Audio from one generated solana account to another.
131
+ * For it to work, you have to have the eth private key belonging to the eth public key
132
+ * that generated the solana account
133
+ *
134
+ * @param {BN} amount amount to send
135
+ * @param {string} senderEthAddress sender's eth address (e.g. you)
136
+ * @param {string} senderEthPrivateKey sender's eth private key
137
+ * @param {string} senderSolanaAddress sender's solana address
138
+ * @param {string} recipientSolanaAddress recipient's solana address
139
+ * @param {string} claimableTokenPDA
140
+ * @param {PublicKey} solanaTokenProgramKey spl token key
141
+ * @param {Connection} connection
142
+ * @returns
143
+ */
144
+ async function transferWAudioBalance ({
145
+ amount,
146
+ senderEthAddress,
147
+ senderEthPrivateKey,
148
+ senderSolanaAddress,
149
+ recipientSolanaAddress,
150
+ claimableTokenPDA,
151
+ solanaTokenProgramKey,
152
+ feePayerKey,
153
+ claimableTokenProgramKey,
154
+ connection,
155
+ mintKey,
156
+ transactionHandler
157
+ }) {
158
+ const senderSolanaPubkey = new PublicKey(senderSolanaAddress)
159
+ const recipientPubkey = new PublicKey(recipientSolanaAddress)
160
+
161
+ const {
162
+ accountNonce,
163
+ nonce
164
+ } = await getAccountNonce({
165
+ connection,
166
+ mintKey,
167
+ ethAddress: senderEthAddress,
168
+ claimableTokenProgramKey
169
+ })
170
+
171
+ const accounts = [
172
+ // 0. `[sw]` Fee payer
173
+ {
174
+ pubkey: feePayerKey,
175
+ isSigner: true,
176
+ isWritable: false
177
+ },
178
+ // 1. `[w]` Token acc from which tokens will be send (bank account)
179
+ {
180
+ pubkey: senderSolanaPubkey,
181
+ isSigner: false,
182
+ isWritable: true
183
+ },
184
+ // 2. `[w]` Receiver token acc
185
+ {
186
+ pubkey: recipientPubkey,
187
+ isSigner: false,
188
+ isWritable: true
189
+ },
190
+ // 3. `[w]` Nonce Account
191
+ {
192
+ pubkey: accountNonce,
193
+ isSigner: false,
194
+ isWritable: true
195
+ },
196
+ // 4. `[r]` Banks token account authority
197
+ {
198
+ pubkey: claimableTokenPDA,
199
+ isSigner: false,
200
+ isWritable: false
201
+ },
202
+ // 5. `[r]` Sysvar Rent id
203
+ {
204
+ pubkey: SYSVAR_RENT_PUBKEY,
205
+ isSigner: false,
206
+ isWritable: false
207
+ },
208
+ // 6. `[r]` Sysvar instruction id
209
+ {
210
+ pubkey: SYSVAR_INSTRUCTIONS_PUBKEY,
211
+ isSigner: false,
212
+ isWritable: false
213
+ },
214
+ // 7. `[r]` System program id
215
+ {
216
+ pubkey: SystemProgram.programId,
217
+ isSigner: false,
218
+ isWritable: false
219
+ },
220
+ // 8. `[r]` SPL token account id
221
+ {
222
+ pubkey: solanaTokenProgramKey,
223
+ isSigner: false,
224
+ isWritable: false
225
+ }
226
+ ]
227
+
228
+ // eth pubkey is different from the ethAddress - addresses are len 20, pub keys are len 64
229
+ const ethPrivateKeyArr = Buffer.from(senderEthPrivateKey, 'hex')
230
+ const ethPubkey = secp256k1.publicKeyCreate(ethPrivateKeyArr, false).slice(1)
231
+
232
+ const instructionData = new TransferInstructionData({
233
+ targetPubKey: recipientPubkey.toBuffer(),
234
+ amount,
235
+ nonce
236
+ })
237
+
238
+ const serializedInstructionData = borsh.serialize(
239
+ transferInstructionDataSchema,
240
+ instructionData
241
+ )
242
+
243
+ const { signature, recoveryId } = SolanaUtils.signBytes(Buffer.from(serializedInstructionData), senderEthPrivateKey)
244
+
245
+ const secpTransactionInstruction = Secp256k1Program.createInstructionWithPublicKey({
246
+ publicKey: Buffer.from(ethPubkey),
247
+ message: Buffer.from(serializedInstructionData),
248
+ signature,
249
+ recoveryId
250
+ })
251
+
252
+ const ethAddressArr = SolanaUtils.ethAddressToArray(senderEthAddress)
253
+ const transferDataInstr = Uint8Array.of(
254
+ 1,
255
+ ...ethAddressArr
256
+ )
257
+
258
+ const instructions = [
259
+ secpTransactionInstruction,
260
+ new TransactionInstruction({
261
+ keys: accounts,
262
+ programId: claimableTokenProgramKey.toString(),
263
+ data: Buffer.from(transferDataInstr)
264
+ })
265
+ ]
266
+ return transactionHandler.handleTransaction({ instructions, errorMapping: ClaimableProgramError, feePayerOverride: feePayerKey })
267
+ }
268
+
269
+ module.exports = {
270
+ deriveTransferNonceAccount,
271
+ transferWAudioBalance
272
+ }
@@ -0,0 +1,160 @@
1
+ const {
2
+ PublicKey,
3
+ SystemProgram,
4
+ SYSVAR_RENT_PUBKEY,
5
+ TransactionInstruction
6
+ } = require('@solana/web3.js')
7
+ const borsh = require('borsh')
8
+ const bs58 = require('bs58')
9
+ const { ethAddressToArray } = require('./utils')
10
+
11
+ class CreateTokenAccountInstructionData {
12
+ constructor ({
13
+ ethAddress
14
+ }) {
15
+ this.hashed_eth_pk = ethAddress
16
+ }
17
+ }
18
+
19
+ const createTokenAccountInstructionSchema = new Map([
20
+ [
21
+ CreateTokenAccountInstructionData,
22
+ {
23
+ kind: 'struct',
24
+ fields: [
25
+ ['hashed_eth_pk', [20]]
26
+ ]
27
+ }
28
+ ]
29
+ ])
30
+
31
+ /**
32
+ * Gets the back account address for a user given their ethAddress
33
+ * @param {string} ethAddress
34
+ * @param {PublicKey} claimableTokenPDA
35
+ * @param {PublicKey} solanaTokenProgramKey
36
+ * @returns
37
+ */
38
+ const getBankAccountAddress = async (
39
+ ethAddress,
40
+ claimableTokenPDA,
41
+ solanaTokenProgramKey
42
+ ) => {
43
+ const ethAddressArr = ethAddressToArray(ethAddress)
44
+
45
+ // We b58 encode our eth address to use as seed later on
46
+ const b58EthAddress = bs58.encode(ethAddressArr)
47
+
48
+ const accountToGenerate = await PublicKey.createWithSeed(
49
+ /* from pubkey / base */ claimableTokenPDA,
50
+ /* seed */ b58EthAddress,
51
+ /* programId / owner */ solanaTokenProgramKey
52
+ )
53
+ return accountToGenerate
54
+ }
55
+
56
+ /**
57
+ * createUserBank deterministically creates a Solana wAudio token account
58
+ * from a provided ethAddress
59
+ * @param {string} ethAddress
60
+ * @param {PublicKey} claimableTokenPDAKey
61
+ * @param {PublicKey} feePayerKey
62
+ * @param {PublicKey} mintKey
63
+ * @param {PublicKey} solanaTokenProgramKey
64
+ * @param {PublicKey} claimableTokenProgramKey
65
+ * @param {*} transactionHandler
66
+ * @param {string?} recentBlockhash
67
+ * @returns
68
+ */
69
+ const createUserBankFrom = async ({
70
+ ethAddress,
71
+ claimableTokenPDAKey,
72
+ feePayerKey,
73
+ mintKey,
74
+ solanaTokenProgramKey,
75
+ claimableTokenProgramKey,
76
+ transactionHandler,
77
+ recentBlockhash
78
+ }) => {
79
+ // Create instruction data
80
+ const ethAddressArr = ethAddressToArray(ethAddress)
81
+
82
+ const instructionData = new CreateTokenAccountInstructionData({
83
+ ethAddress: ethAddressArr
84
+ })
85
+ const serializedInstructionData = borsh.serialize(
86
+ createTokenAccountInstructionSchema,
87
+ instructionData
88
+ )
89
+
90
+ // 0th index in the Rust instruction enum
91
+ const serializedInstructionEnum = Uint8Array.of(
92
+ 0,
93
+ ...serializedInstructionData
94
+ )
95
+
96
+ // Create the account we aim to generate
97
+ const accountToGenerate = await getBankAccountAddress(
98
+ ethAddress,
99
+ claimableTokenPDAKey,
100
+ solanaTokenProgramKey
101
+ )
102
+
103
+ const accounts = [
104
+ // 0. `[sw]` Account to pay for creating token acc
105
+ {
106
+ pubkey: feePayerKey,
107
+ isSigner: true,
108
+ isWritable: true
109
+ },
110
+ // 1. `[r]` Mint account
111
+ {
112
+ pubkey: mintKey,
113
+ isSigner: false,
114
+ isWritable: false
115
+ },
116
+ // 2. `[r]` Base acc used in PDA token acc (need because of create_with_seed instruction)
117
+ {
118
+ pubkey: claimableTokenPDAKey,
119
+ isSigner: false,
120
+ isWritable: false
121
+ },
122
+ // 3. `[w]` PDA token account to create
123
+ {
124
+ pubkey: accountToGenerate,
125
+ isSigner: false,
126
+ isWritable: true
127
+ },
128
+ // `[r]` Rent id
129
+ {
130
+ pubkey: SYSVAR_RENT_PUBKEY,
131
+ isSigner: false,
132
+ isWritable: false
133
+ },
134
+ // 5. `[r]` SPL token account id
135
+ {
136
+ pubkey: solanaTokenProgramKey,
137
+ isSigner: false,
138
+ isWritable: false
139
+ },
140
+ // 6. `[r]` System program id
141
+ {
142
+ pubkey: SystemProgram.programId,
143
+ isSigner: false,
144
+ isWritable: false
145
+ }
146
+ ]
147
+
148
+ const instructions = [new TransactionInstruction({
149
+ keys: accounts,
150
+ programId: claimableTokenProgramKey.toString(),
151
+ data: Buffer.from(serializedInstructionEnum)
152
+ })]
153
+
154
+ return transactionHandler.handleTransaction({ instructions, recentBlockhash, feePayerOverride: feePayerKey })
155
+ }
156
+
157
+ module.exports = {
158
+ getBankAccountAddress,
159
+ createUserBankFrom
160
+ }
@@ -0,0 +1,31 @@
1
+ export default class SolanaUtils {
2
+ static signBytes: (bytes: any, ethPrivateKey: any) => any
3
+ static prepareInstructionForRelay: (instruction: any) => any
4
+ static constructTransferId: (challengeId: any, specifier: any) => string
5
+
6
+ static constructAttestation: (
7
+ recipientEthAddress: any,
8
+ tokenAmount: any,
9
+ transferId: any,
10
+ oracleAddress: any
11
+ ) => any
12
+
13
+ static uiAudioToBNWaudio: (amount: any) => any
14
+
15
+ static findProgramAddressFromPubkey: (
16
+ programId: any,
17
+ pubkey: any,
18
+ seed: any
19
+ ) => Promise<any>
20
+
21
+ static findProgramAddressWithAuthority: (
22
+ programId: any,
23
+ address: any,
24
+ seed: any
25
+ ) => Promise<any>
26
+
27
+ static ethAddressToArray: (ethAddress: any) => any
28
+
29
+ // Safely create pubkey from nullable val
30
+ static newPublicKeyNullable: (val: any) => any
31
+ }
@@ -0,0 +1,163 @@
1
+ const { padBNToUint8Array } = require('./padBNToUint8Array')
2
+ const { PublicKey } = require('@solana/web3.js')
3
+ const BN = require('bn.js')
4
+ const keccak256 = require('keccak256')
5
+ const secp256k1 = require('secp256k1')
6
+ const { WAUDIO_DECMIALS } = require('../../constants')
7
+ class SolanaUtils {
8
+ /**
9
+ * Signs arbitrary bytes
10
+ *
11
+ * @param {*} bytes
12
+ * @param {string} ethPrivateKey
13
+ */
14
+ static signBytes (bytes, ethPrivateKey) {
15
+ const msgHash = keccak256(bytes)
16
+ const ethPrivateKeyArr = Buffer.from(ethPrivateKey, 'hex')
17
+ const signatureObj = secp256k1.ecdsaSign(
18
+ Uint8Array.from(msgHash),
19
+ ethPrivateKeyArr
20
+ )
21
+ const signature = Buffer.from(signatureObj.signature)
22
+ return {
23
+ signature,
24
+ recoveryId: signatureObj.recid
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Puts an instruction in a serializable form that our relay can understand.
30
+ *
31
+ * @param {TransactionInstruction} instruction
32
+ */
33
+ static prepareInstructionForRelay (instruction) {
34
+ return {
35
+ programId: instruction.programId.toString(),
36
+ data: instruction.data,
37
+ keys: instruction.keys.map(({ isSigner, pubkey, isWritable }) => ({
38
+ pubkey: pubkey.toString(),
39
+ isSigner,
40
+ isWritable
41
+ }))
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Constructs a transfer ID
47
+ * @param {string} challengeId
48
+ * @param {string} specifier
49
+ * @returns {string}
50
+ */
51
+ static constructTransferId (challengeId, specifier) {
52
+ return `${challengeId}:${specifier}`
53
+ }
54
+
55
+ /**
56
+ * Constructs an attestation from inputs.
57
+ *
58
+ * @param {string} recipientEthAddress
59
+ * @param {BN} tokenAmount
60
+ * @param {string} transferId
61
+ * @param {string} [oracleAddress] optional oracle address, only used for DN attestations
62
+ * @returns {Uint8Array}
63
+ */
64
+ static constructAttestation (
65
+ recipientEthAddress,
66
+ tokenAmount,
67
+ transferId,
68
+ oracleAddress
69
+ ) {
70
+ const encoder = new TextEncoder()
71
+ const userBytes = SolanaUtils.ethAddressToArray(recipientEthAddress)
72
+ const transferIdBytes = encoder.encode(transferId)
73
+ const amountBytes = padBNToUint8Array(tokenAmount)
74
+ const items = oracleAddress
75
+ ? [
76
+ userBytes,
77
+ amountBytes,
78
+ transferIdBytes,
79
+ SolanaUtils.ethAddressToArray(oracleAddress)
80
+ ]
81
+ : [userBytes, amountBytes, transferIdBytes]
82
+ const sep = encoder.encode('_')
83
+ const res = items.slice(1).reduce((prev, cur, i) => {
84
+ return Uint8Array.of(...prev, ...sep, ...cur)
85
+ }, Uint8Array.from(items[0]))
86
+ return res
87
+ }
88
+
89
+ /**
90
+ * Converts "UI" wAudio (i.e. 5) into properly denominated BN representation - (i.e. 5 * 10 ^ 8)
91
+ *
92
+ * @param {number} amount
93
+ * @returns BN
94
+ * @memberof SolanaWeb3Manager
95
+ */
96
+ static uiAudioToBNWaudio (amount) {
97
+ return new BN(amount * 10 ** WAUDIO_DECMIALS)
98
+ }
99
+
100
+ /**
101
+ * Derives a program address from a program ID and pubkey as seed.
102
+ * Optionally takes in seeds.
103
+ * Returns the new pubkey and bump seeds.
104
+ *
105
+ * @param {PublicKey} programId
106
+ * @param {PublicKey} pubkey
107
+ * @param {Uint8Array} [seed] optionally include a seed
108
+ * @returns {Promise<[PublicKey, number]>}
109
+ */
110
+ static async findProgramAddressFromPubkey (programId, pubkey, seed) {
111
+ const seedsArr = [pubkey.toBytes().slice(0, 32)]
112
+ if (seed) {
113
+ seedsArr.push(seed)
114
+ }
115
+ return PublicKey.findProgramAddress(seedsArr, programId)
116
+ }
117
+
118
+ /**
119
+ * Finds a program address, using both seeds, pubkey, and the derived authority.
120
+ * Return [authority, derivedAddress, and bumpSeeds]
121
+ *
122
+ * @param {PublicKey} programId
123
+ * @param {PublicKey} address
124
+ * @param {Uint8Array} seed
125
+ * @returns {Promise<[PublicKey, PublicKey, number]>}
126
+ */
127
+ static async findProgramAddressWithAuthority (programId, address, seed) {
128
+ // Finds the authority account by generating a PDA with the address as a seed
129
+ const [authority] = await SolanaUtils.findProgramAddressFromPubkey(
130
+ programId,
131
+ address
132
+ )
133
+
134
+ const [derivedAddress, bumpSeed] =
135
+ await SolanaUtils.findProgramAddressFromPubkey(
136
+ programId,
137
+ authority,
138
+ seed
139
+ )
140
+ return [authority, derivedAddress, bumpSeed]
141
+ }
142
+
143
+ /**
144
+ * Converts an eth address hex represenatation to an array of Uint8s in big endian notation
145
+ * @param {string} ethAddress
146
+ * @returns {Uint8Array}
147
+ */
148
+ static ethAddressToArray (ethAddress) {
149
+ const strippedEthAddress = ethAddress.replace('0x', '')
150
+ // Need to pad the array to length 20 - otherwise, hex eth keys starting with '0' would
151
+ // result in truncated arrays, while eth spec is always 20 bytes
152
+ return Uint8Array.of(
153
+ ...new BN(strippedEthAddress, 'hex').toArray('be', 20)
154
+ )
155
+ }
156
+
157
+ // Safely create pubkey from nullable val
158
+ static newPublicKeyNullable (val) {
159
+ return val ? new PublicKey(val) : null
160
+ }
161
+ }
162
+
163
+ module.exports = SolanaUtils
@@ -0,0 +1,28 @@
1
+ const BN = require('bn.js')
2
+
3
+ const MIN_WAUDIO_AMOUNT = new BN('10000000000') // 10^10
4
+
5
+ /**
6
+ * Converts Wei Audio (BN) to wAudio (BN).
7
+ * wAudio has only 8 digits of precision vs. 18 in Wei Audio.
8
+ * The amount must be >= 10^10 and have no remainder when divided by 10^10.
9
+ * @param {BN} amount Wei Audio amount
10
+ */
11
+ const wAudioFromWeiAudio = (amount) => {
12
+ if (amount.lt(MIN_WAUDIO_AMOUNT)) {
13
+ throw new Error(
14
+ `${amount.toString()} is below minimum bounds ${MIN_WAUDIO_AMOUNT.toString()}`
15
+ )
16
+ }
17
+ const { div, mod } = amount.divmod(MIN_WAUDIO_AMOUNT)
18
+ if (!mod.isZero()) {
19
+ throw new Error(
20
+ `${amount.toString()} is too precise for conversion to wAudio. Remainder: ${mod.toString()}`
21
+ )
22
+ }
23
+ return div
24
+ }
25
+
26
+ module.exports = {
27
+ wAudioFromWeiAudio
28
+ }
@@ -0,0 +1,30 @@
1
+ const BN = require('bn.js')
2
+ const assert = require('assert')
3
+
4
+ const { wAudioFromWeiAudio } = require('./wAudio')
5
+
6
+ describe('wAudioFromWeiAudio', () => {
7
+ it('throws if the amount is below the minimum', () => {
8
+ const weiAudio = new BN('1')
9
+ assert.throws(() => wAudioFromWeiAudio(weiAudio))
10
+ })
11
+ it('throws if the amount too precise', () => {
12
+ const weiAudio = new BN('100000001')
13
+ assert.throws(() => wAudioFromWeiAudio(weiAudio))
14
+ })
15
+ it('converts if the amount equals the minimum', () => {
16
+ const weiAudio = new BN('10000000000')
17
+ const wAudio = wAudioFromWeiAudio(weiAudio)
18
+ assert.ok(wAudio.eq(new BN('1')))
19
+ })
20
+ it('converts if the amount is valid', () => {
21
+ const weiAudio = new BN('10240000000000') // 1024 * 10^-10 $AUDIO
22
+ const wAudio = wAudioFromWeiAudio(weiAudio)
23
+ assert.ok(wAudio.eq(new BN('1024')))
24
+ })
25
+ it('converts if the amount is large and valid', () => {
26
+ const weiAudio = new BN('49000000000000000000') // 49 $AUDIO
27
+ const wAudio = wAudioFromWeiAudio(weiAudio)
28
+ assert.ok(wAudio.eq(new BN('4900000000')))
29
+ })
30
+ })
@@ -0,0 +1,14 @@
1
+ import type Web3 from 'web3'
2
+ import type Wallet from 'ethereumjs-wallet'
3
+
4
+ export type Web3Config = {
5
+ useExternalWeb3: boolean
6
+ internalWeb3Config: {
7
+ web3ProviderEndpoints: string[]
8
+ privateKey?: string
9
+ }
10
+ externalWeb3Config?: {
11
+ web3: Web3
12
+ ownerWallet: Wallet
13
+ }
14
+ }