@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.
- package/.eslintrc +38 -0
- package/.prettierrc.js +1 -0
- package/.python-version +1 -0
- package/Dockerfile +15 -0
- package/README.md +3 -0
- package/babel.config.js +3 -0
- package/data-contracts/ABIs/AdminUpgradeabilityProxy.json +132 -0
- package/data-contracts/ABIs/BaseAdminUpgradeabilityProxy.json +113 -0
- package/data-contracts/ABIs/BaseUpgradeabilityProxy.json +22 -0
- package/data-contracts/ABIs/DiscoveryProviderFactory.json +189 -0
- package/data-contracts/ABIs/DiscoveryProviderFactoryInterface.json +61 -0
- package/data-contracts/ABIs/DiscoveryProviderStorage.json +205 -0
- package/data-contracts/ABIs/DiscoveryProviderStorageInterface.json +65 -0
- package/data-contracts/ABIs/ECDSA.json +4 -0
- package/data-contracts/ABIs/IPLDBlacklistFactory.json +168 -0
- package/data-contracts/ABIs/Initializable.json +4 -0
- package/data-contracts/ABIs/Migrations.json +67 -0
- package/data-contracts/ABIs/OpenZeppelinUpgradesAddress.json +4 -0
- package/data-contracts/ABIs/Ownable.json +79 -0
- package/data-contracts/ABIs/PlaylistFactory.json +669 -0
- package/data-contracts/ABIs/PlaylistFactoryInterface.json +42 -0
- package/data-contracts/ABIs/PlaylistStorage.json +250 -0
- package/data-contracts/ABIs/PlaylistStorageInterface.json +129 -0
- package/data-contracts/ABIs/Proxy.json +10 -0
- package/data-contracts/ABIs/Registry.json +240 -0
- package/data-contracts/ABIs/RegistryContract.json +102 -0
- package/data-contracts/ABIs/RegistryContractInterface.json +28 -0
- package/data-contracts/ABIs/RegistryInterface.json +66 -0
- package/data-contracts/ABIs/SigningLogic.json +43 -0
- package/data-contracts/ABIs/SigningLogicInitializable.json +46 -0
- package/data-contracts/ABIs/SocialFeatureFactory.json +460 -0
- package/data-contracts/ABIs/SocialFeatureStorage.json +225 -0
- package/data-contracts/ABIs/SocialFeatureStorageInterface.json +123 -0
- package/data-contracts/ABIs/TestContract.json +135 -0
- package/data-contracts/ABIs/TestContractInterface.json +19 -0
- package/data-contracts/ABIs/TestContractWithStorage.json +165 -0
- package/data-contracts/ABIs/TestContractWithStorageInterface.json +24 -0
- package/data-contracts/ABIs/TestStorage.json +144 -0
- package/data-contracts/ABIs/TestStorageInterface.json +42 -0
- package/data-contracts/ABIs/TestUserReplicaSetManager.json +432 -0
- package/data-contracts/ABIs/TrackFactory.json +391 -0
- package/data-contracts/ABIs/TrackFactoryInterface.json +73 -0
- package/data-contracts/ABIs/TrackStorage.json +223 -0
- package/data-contracts/ABIs/TrackStorageInterface.json +121 -0
- package/data-contracts/ABIs/UpgradeabilityProxy.json +37 -0
- package/data-contracts/ABIs/UserFactory.json +657 -0
- package/data-contracts/ABIs/UserFactoryInterface.json +65 -0
- package/data-contracts/ABIs/UserLibraryFactory.json +334 -0
- package/data-contracts/ABIs/UserReplicaSetManager.json +418 -0
- package/data-contracts/ABIs/UserStorage.json +233 -0
- package/data-contracts/ABIs/UserStorageInterface.json +93 -0
- package/data-contracts/signatureSchemas.ts +1236 -0
- package/dist/core.d.ts +446 -0
- package/dist/core.js +769 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +689 -0
- package/dist/index.js +72850 -0
- package/dist/index.js.map +1 -0
- package/eth-contracts/ABIs/Address.json +4 -0
- package/eth-contracts/ABIs/AudiusAdminUpgradeabilityProxy.json +105 -0
- package/eth-contracts/ABIs/AudiusClaimDistributor.json +4968 -0
- package/eth-contracts/ABIs/AudiusToken.json +724 -0
- package/eth-contracts/ABIs/BaseUpgradeabilityProxy.json +23 -0
- package/eth-contracts/ABIs/Checkpointing.json +4 -0
- package/eth-contracts/ABIs/ClaimsManager.json +539 -0
- package/eth-contracts/ABIs/Context.json +11 -0
- package/eth-contracts/ABIs/DelegateManager.json +989 -0
- package/eth-contracts/ABIs/DelegateManagerV2.json +1049 -0
- package/eth-contracts/ABIs/DelegateManagerV2Bad.json +1049 -0
- package/eth-contracts/ABIs/ERC20.json +252 -0
- package/eth-contracts/ABIs/ERC20Burnable.json +287 -0
- package/eth-contracts/ABIs/ERC20Detailed.json +270 -0
- package/eth-contracts/ABIs/ERC20Mintable.json +364 -0
- package/eth-contracts/ABIs/ERC20Pausable.json +397 -0
- package/eth-contracts/ABIs/EthRewardsManager.json +174 -0
- package/eth-contracts/ABIs/Governance.json +938 -0
- package/eth-contracts/ABIs/GovernanceUpgraded.json +953 -0
- package/eth-contracts/ABIs/GovernanceV2.json +938 -0
- package/eth-contracts/ABIs/IERC20.json +200 -0
- package/eth-contracts/ABIs/Initializable.json +4 -0
- package/eth-contracts/ABIs/InitializableV2.json +14 -0
- package/eth-contracts/ABIs/Migrations.json +71 -0
- package/eth-contracts/ABIs/MinterRole.json +91 -0
- package/eth-contracts/ABIs/MockAccount.json +62 -0
- package/eth-contracts/ABIs/MockDelegateManager.json +55 -0
- package/eth-contracts/ABIs/MockStakingCaller.json +259 -0
- package/eth-contracts/ABIs/MockWormhole.json +106 -0
- package/eth-contracts/ABIs/OpenZeppelinUpgradesAddress.json +4 -0
- package/eth-contracts/ABIs/Ownable.json +93 -0
- package/eth-contracts/ABIs/Pausable.json +150 -0
- package/eth-contracts/ABIs/PauserRole.json +91 -0
- package/eth-contracts/ABIs/Proxy.json +10 -0
- package/eth-contracts/ABIs/Registry.json +288 -0
- package/eth-contracts/ABIs/Roles.json +4 -0
- package/eth-contracts/ABIs/SafeERC20.json +4 -0
- package/eth-contracts/ABIs/SafeMath.json +4 -0
- package/eth-contracts/ABIs/ServiceProviderFactory.json +1153 -0
- package/eth-contracts/ABIs/ServiceTypeManager.json +337 -0
- package/eth-contracts/ABIs/Staking.json +555 -0
- package/eth-contracts/ABIs/StakingUpgraded.json +570 -0
- package/eth-contracts/ABIs/TestContract.json +44 -0
- package/eth-contracts/ABIs/TrustedNotifierManager.json +265 -0
- package/eth-contracts/ABIs/Uint256Helpers.json +4 -0
- package/eth-contracts/ABIs/UpgradeabilityProxy.json +40 -0
- package/eth-contracts/ABIs/Wormhole.json +45 -0
- package/eth-contracts/ABIs/WormholeClient.json +155 -0
- package/examples/file.mp3 +0 -0
- package/examples/initAudiusLibs.js +86 -0
- package/examples/initializeVersions.js +95 -0
- package/examples/pic.jpg +0 -0
- package/initScripts/configureLocalDiscProv.js +167 -0
- package/initScripts/helpers/claim.js +43 -0
- package/initScripts/helpers/distributeTokens.js +24 -0
- package/initScripts/helpers/spRegistration.js +138 -0
- package/initScripts/helpers/utils.js +34 -0
- package/initScripts/helpers/version.js +93 -0
- package/initScripts/local.js +617 -0
- package/initScripts/mainnet.js +131 -0
- package/initScripts/manageProdRelayerWallets.js +191 -0
- package/package.json +125 -0
- package/rollup.config.js +164 -0
- package/scripts/AudiusClaimDistributor.json +4968 -0
- package/scripts/Wormhole.json +155 -0
- package/scripts/addCIDToIpldBlacklist.js +124 -0
- package/scripts/circleci-test.sh +53 -0
- package/scripts/communityRewards/transferCommunityRewardsToSolana.js +222 -0
- package/scripts/ipfs.sh +58 -0
- package/scripts/migrate_contracts.sh +25 -0
- package/scripts/reset.sh +65 -0
- package/scripts/test.sh +77 -0
- package/src/api/account.js +670 -0
- package/src/api/base.js +122 -0
- package/src/api/file.js +168 -0
- package/src/api/playlist.js +328 -0
- package/src/api/rewards.d.ts +4 -0
- package/src/api/rewards.js +682 -0
- package/src/api/serviceProvider.js +154 -0
- package/src/api/track.js +604 -0
- package/src/api/user.js +888 -0
- package/src/api/user.test.js +172 -0
- package/src/constants.ts +7 -0
- package/src/core.ts +3 -0
- package/src/index.js +6 -0
- package/src/libs.d.ts +3 -0
- package/src/libs.js +619 -0
- package/src/sanityChecks/addSecondaries.js +40 -0
- package/src/sanityChecks/assignReplicaSetIfNecessary.js +10 -0
- package/src/sanityChecks/index.d.ts +9 -0
- package/src/sanityChecks/index.js +31 -0
- package/src/sanityChecks/isCreator.js +73 -0
- package/src/sanityChecks/needsRecoveryEmail.js +20 -0
- package/src/sanityChecks/rolloverNodes.js +74 -0
- package/src/sanityChecks/sanitizeNodes.js +24 -0
- package/src/sanityChecks/syncNodes.js +28 -0
- package/src/sdk/constants.ts +10 -0
- package/src/sdk/index.ts +1 -0
- package/src/sdk/oauth/Oauth.ts +265 -0
- package/src/sdk/oauth/index.ts +1 -0
- package/src/sdk/sdk.ts +102 -0
- package/src/service-selection/ServiceSelection.test.ts +320 -0
- package/src/service-selection/ServiceSelection.ts +460 -0
- package/src/service-selection/constants.ts +14 -0
- package/src/service-selection/index.ts +1 -0
- package/src/services/ABIDecoder/AudiusABIDecoder.ts +71 -0
- package/src/services/ABIDecoder/index.ts +1 -0
- package/src/services/comstock/Comstock.ts +39 -0
- package/src/services/comstock/index.ts +1 -0
- package/src/services/contracts/ContractClient.ts +227 -0
- package/src/services/contracts/GovernedContractClient.ts +53 -0
- package/src/services/contracts/ProviderSelection.ts +42 -0
- package/src/services/creatorNode/CreatorNode.ts +1065 -0
- package/src/services/creatorNode/CreatorNodeSelection.test.ts +997 -0
- package/src/services/creatorNode/CreatorNodeSelection.ts +488 -0
- package/src/services/creatorNode/constants.ts +10 -0
- package/src/services/creatorNode/index.ts +2 -0
- package/src/services/dataContracts/AudiusContracts.ts +234 -0
- package/src/services/dataContracts/IPLDBlacklistFactoryClient.ts +73 -0
- package/src/services/dataContracts/PlaylistFactoryClient.ts +370 -0
- package/src/services/dataContracts/RegistryClient.ts +95 -0
- package/src/services/dataContracts/SocialFeatureFactoryClient.ts +196 -0
- package/src/services/dataContracts/TrackFactoryClient.ts +131 -0
- package/src/services/dataContracts/UserFactoryClient.ts +351 -0
- package/src/services/dataContracts/UserLibraryFactoryClient.ts +115 -0
- package/src/services/dataContracts/UserReplicaSetManagerClient.ts +206 -0
- package/src/services/dataContracts/index.ts +1 -0
- package/src/services/discoveryProvider/DiscoveryProvider.ts +1168 -0
- package/src/services/discoveryProvider/DiscoveryProviderSelection.test.ts +536 -0
- package/src/services/discoveryProvider/DiscoveryProviderSelection.ts +383 -0
- package/src/services/discoveryProvider/constants.ts +13 -0
- package/src/services/discoveryProvider/index.ts +1 -0
- package/src/services/discoveryProvider/requests.ts +629 -0
- package/src/services/ethContracts/AudiusTokenClient.ts +163 -0
- package/src/services/ethContracts/ClaimDistributionClient.ts +45 -0
- package/src/services/ethContracts/ClaimsManagerClient.ts +102 -0
- package/src/services/ethContracts/DelegateManagerClient.ts +480 -0
- package/src/services/ethContracts/EthContracts.ts +359 -0
- package/src/services/ethContracts/EthRewardsManagerClient.ts +33 -0
- package/src/services/ethContracts/GovernanceClient.ts +451 -0
- package/src/services/ethContracts/RegistryClient.ts +33 -0
- package/src/services/ethContracts/ServiceProviderFactoryClient.ts +691 -0
- package/src/services/ethContracts/ServiceTypeManagerClient.ts +112 -0
- package/src/services/ethContracts/StakingProxyClient.ts +97 -0
- package/src/services/ethContracts/TrustedNotifierManagerClient.ts +101 -0
- package/src/services/ethContracts/WormholeClient.ts +97 -0
- package/src/services/ethContracts/index.ts +1 -0
- package/src/services/ethWeb3Manager/EthWeb3Manager.ts +239 -0
- package/src/services/ethWeb3Manager/index.ts +1 -0
- package/src/services/hedgehog/Hedgehog.ts +96 -0
- package/src/services/hedgehog/index.ts +1 -0
- package/src/services/identity/IdentityService.ts +551 -0
- package/src/services/identity/index.ts +1 -0
- package/src/services/identity/requests.ts +65 -0
- package/src/services/schemaValidator/SchemaValidator.ts +105 -0
- package/src/services/schemaValidator/index.ts +1 -0
- package/src/services/schemaValidator/schemas/trackSchema.json +267 -0
- package/src/services/schemaValidator/schemas/userSchema.json +230 -0
- package/src/services/solanaAudiusData/errors.ts +20 -0
- package/src/services/solanaAudiusData/index.ts +1189 -0
- package/src/services/solanaWeb3Manager/errors.js +101 -0
- package/src/services/solanaWeb3Manager/index.d.ts +46 -0
- package/src/services/solanaWeb3Manager/index.js +655 -0
- package/src/services/solanaWeb3Manager/padBNToUint8Array.ts +7 -0
- package/src/services/solanaWeb3Manager/rewards.js +941 -0
- package/src/services/solanaWeb3Manager/rewardsAttester.ts +1093 -0
- package/src/services/solanaWeb3Manager/tokenAccount.js +149 -0
- package/src/services/solanaWeb3Manager/transactionHandler.js +345 -0
- package/src/services/solanaWeb3Manager/transfer.js +272 -0
- package/src/services/solanaWeb3Manager/userBank.js +160 -0
- package/src/services/solanaWeb3Manager/utils.d.ts +31 -0
- package/src/services/solanaWeb3Manager/utils.js +163 -0
- package/src/services/solanaWeb3Manager/wAudio.js +28 -0
- package/src/services/solanaWeb3Manager/wAudio.test.js +30 -0
- package/src/services/web3Manager/Web3Config.ts +14 -0
- package/src/services/web3Manager/Web3Manager.ts +360 -0
- package/src/services/web3Manager/XMLHttpRequest.ts +11 -0
- package/src/services/web3Manager/index.ts +2 -0
- package/src/services/wormhole/index.js +424 -0
- package/src/types.ts +8 -0
- package/src/userStateManager.ts +53 -0
- package/src/utils/apiSigning.ts +51 -0
- package/src/utils/captcha.ts +97 -0
- package/src/utils/estimateGas.ts +64 -0
- package/src/utils/fileHasher.ts +278 -0
- package/src/utils/importContractABI.d.ts +9 -0
- package/src/utils/importContractABI.js +19 -0
- package/src/utils/index.ts +11 -0
- package/src/utils/multiProvider.ts +72 -0
- package/src/utils/network.test.ts +127 -0
- package/src/utils/network.ts +308 -0
- package/src/utils/promiseFight.test.ts +87 -0
- package/src/utils/promiseFight.ts +36 -0
- package/src/utils/signatures.ts +139 -0
- package/src/utils/types.ts +34 -0
- package/src/utils/utils.test.ts +36 -0
- package/src/utils/utils.ts +235 -0
- package/src/utils/uuid.ts +14 -0
- package/src/web3.d.ts +9 -0
- package/src/web3.js +8 -0
- package/tests/assets/static_image.png +0 -0
- package/tests/assets/static_text.txt +1 -0
- package/tests/audiusTokenClientTest.js +37 -0
- package/tests/creatorNodeTest.js +19 -0
- package/tests/fileHasherTest.js +125 -0
- package/tests/governanceTest.js +382 -0
- package/tests/helpers.js +105 -0
- package/tests/index.js +14 -0
- package/tests/playlistClientTest.js +157 -0
- package/tests/providerSelectionTest.js +241 -0
- package/tests/registryClientTest.js +19 -0
- package/tests/rewardsAttesterTest.js +373 -0
- package/tests/serviceTypeManagerClientTest.js +33 -0
- package/tests/socialFeatureClientTest.js +79 -0
- package/tests/stakingTest.js +302 -0
- package/tests/trackClientTest.js +86 -0
- package/tests/userClientTest.js +121 -0
- package/tsconfig.json +10 -0
- package/types/@audius-hedgehog/index.d.ts +39 -0
- 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
|
+
}
|