@towns-labs/web3 2.0.1
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/README.md +3 -0
- package/dist/BaseContractShim.d.ts +57 -0
- package/dist/BaseContractShim.d.ts.map +1 -0
- package/dist/BaseContractShim.js +224 -0
- package/dist/BaseContractShim.js.map +1 -0
- package/dist/airdrop/IDropFacetShim.d.ts +9 -0
- package/dist/airdrop/IDropFacetShim.d.ts.map +1 -0
- package/dist/airdrop/IDropFacetShim.js +9 -0
- package/dist/airdrop/IDropFacetShim.js.map +1 -0
- package/dist/airdrop/IRiverPointsShim.d.ts +9 -0
- package/dist/airdrop/IRiverPointsShim.d.ts.map +1 -0
- package/dist/airdrop/IRiverPointsShim.js +9 -0
- package/dist/airdrop/IRiverPointsShim.js.map +1 -0
- package/dist/airdrop/RiverAirdropDapp.d.ts +16 -0
- package/dist/airdrop/RiverAirdropDapp.d.ts.map +1 -0
- package/dist/airdrop/RiverAirdropDapp.js +30 -0
- package/dist/airdrop/RiverAirdropDapp.js.map +1 -0
- package/dist/app-registry/AppRegistryDapp.d.ts +68 -0
- package/dist/app-registry/AppRegistryDapp.d.ts.map +1 -0
- package/dist/app-registry/AppRegistryDapp.js +182 -0
- package/dist/app-registry/AppRegistryDapp.js.map +1 -0
- package/dist/app-registry/IAppFactoryShim.d.ts +9 -0
- package/dist/app-registry/IAppFactoryShim.d.ts.map +1 -0
- package/dist/app-registry/IAppFactoryShim.js +9 -0
- package/dist/app-registry/IAppFactoryShim.js.map +1 -0
- package/dist/app-registry/IAppInstallerShim.d.ts +9 -0
- package/dist/app-registry/IAppInstallerShim.d.ts.map +1 -0
- package/dist/app-registry/IAppInstallerShim.js +9 -0
- package/dist/app-registry/IAppInstallerShim.js.map +1 -0
- package/dist/app-registry/IAppRegistryShim.d.ts +9 -0
- package/dist/app-registry/IAppRegistryShim.d.ts.map +1 -0
- package/dist/app-registry/IAppRegistryShim.js +9 -0
- package/dist/app-registry/IAppRegistryShim.js.map +1 -0
- package/dist/app-registry/IIdentityRegistryShim.d.ts +9 -0
- package/dist/app-registry/IIdentityRegistryShim.d.ts.map +1 -0
- package/dist/app-registry/IIdentityRegistryShim.js +9 -0
- package/dist/app-registry/IIdentityRegistryShim.js.map +1 -0
- package/dist/app-registry/IReputationRegistryShim.d.ts +9 -0
- package/dist/app-registry/IReputationRegistryShim.d.ts.map +1 -0
- package/dist/app-registry/IReputationRegistryShim.js +9 -0
- package/dist/app-registry/IReputationRegistryShim.js.map +1 -0
- package/dist/app-registry/SimpleAppShim.d.ts +9 -0
- package/dist/app-registry/SimpleAppShim.d.ts.map +1 -0
- package/dist/app-registry/SimpleAppShim.js +9 -0
- package/dist/app-registry/SimpleAppShim.js.map +1 -0
- package/dist/base-registry/BaseRegistry.d.ts +32 -0
- package/dist/base-registry/BaseRegistry.d.ts.map +1 -0
- package/dist/base-registry/BaseRegistry.js +67 -0
- package/dist/base-registry/BaseRegistry.js.map +1 -0
- package/dist/base-registry/IEntitlementCheckerShim.d.ts +9 -0
- package/dist/base-registry/IEntitlementCheckerShim.d.ts.map +1 -0
- package/dist/base-registry/IEntitlementCheckerShim.js +9 -0
- package/dist/base-registry/IEntitlementCheckerShim.js.map +1 -0
- package/dist/base-registry/INodeOperatorShim.d.ts +9 -0
- package/dist/base-registry/INodeOperatorShim.d.ts.map +1 -0
- package/dist/base-registry/INodeOperatorShim.js +9 -0
- package/dist/base-registry/INodeOperatorShim.js.map +1 -0
- package/dist/base-registry/ISpaceDelegationShim.d.ts +9 -0
- package/dist/base-registry/ISpaceDelegationShim.d.ts.map +1 -0
- package/dist/base-registry/ISpaceDelegationShim.js +9 -0
- package/dist/base-registry/ISpaceDelegationShim.js.map +1 -0
- package/dist/base-registry/RewardsDistributionShim.d.ts +9 -0
- package/dist/base-registry/RewardsDistributionShim.d.ts.map +1 -0
- package/dist/base-registry/RewardsDistributionShim.js +9 -0
- package/dist/base-registry/RewardsDistributionShim.js.map +1 -0
- package/dist/cache/EntitlementCache.d.ts +25 -0
- package/dist/cache/EntitlementCache.d.ts.map +1 -0
- package/dist/cache/EntitlementCache.js +91 -0
- package/dist/cache/EntitlementCache.js.map +1 -0
- package/dist/cache/ICacheStorage.d.ts +44 -0
- package/dist/cache/ICacheStorage.d.ts.map +1 -0
- package/dist/cache/ICacheStorage.js +2 -0
- package/dist/cache/ICacheStorage.js.map +1 -0
- package/dist/cache/KVCacheStorage.d.ts +79 -0
- package/dist/cache/KVCacheStorage.d.ts.map +1 -0
- package/dist/cache/KVCacheStorage.js +227 -0
- package/dist/cache/KVCacheStorage.js.map +1 -0
- package/dist/cache/Keyable.d.ts +20 -0
- package/dist/cache/Keyable.d.ts.map +1 -0
- package/dist/cache/Keyable.js +62 -0
- package/dist/cache/Keyable.js.map +1 -0
- package/dist/cache/SimpleCache.d.ts +30 -0
- package/dist/cache/SimpleCache.d.ts.map +1 -0
- package/dist/cache/SimpleCache.js +84 -0
- package/dist/cache/SimpleCache.js.map +1 -0
- package/dist/cache/TTLCacheStorage.d.ts +19 -0
- package/dist/cache/TTLCacheStorage.d.ts.map +1 -0
- package/dist/cache/TTLCacheStorage.js +40 -0
- package/dist/cache/TTLCacheStorage.js.map +1 -0
- package/dist/chain.d.ts +89 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +48 -0
- package/dist/chain.js.map +1 -0
- package/dist/delegate-registry/DelegateRegistry.d.ts +3 -0
- package/dist/delegate-registry/DelegateRegistry.d.ts.map +1 -0
- package/dist/delegate-registry/DelegateRegistry.js +72 -0
- package/dist/delegate-registry/DelegateRegistry.js.map +1 -0
- package/dist/eip-712/EIP-712.d.ts +35 -0
- package/dist/eip-712/EIP-712.d.ts.map +1 -0
- package/dist/eip-712/EIP-712.js +57 -0
- package/dist/eip-712/EIP-712.js.map +1 -0
- package/dist/erc-721/IERC721AQueryableShim.d.ts +9 -0
- package/dist/erc-721/IERC721AQueryableShim.d.ts.map +1 -0
- package/dist/erc-721/IERC721AQueryableShim.js +9 -0
- package/dist/erc-721/IERC721AQueryableShim.js.map +1 -0
- package/dist/erc-721/IERC721AShim.d.ts +9 -0
- package/dist/erc-721/IERC721AShim.d.ts.map +1 -0
- package/dist/erc-721/IERC721AShim.js +9 -0
- package/dist/erc-721/IERC721AShim.js.map +1 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/dist/platform-requirements/PlatformRequirements.d.ts +12 -0
- package/dist/platform-requirements/PlatformRequirements.d.ts.map +1 -0
- package/dist/platform-requirements/PlatformRequirements.js +18 -0
- package/dist/platform-requirements/PlatformRequirements.js.map +1 -0
- package/dist/pricing-modules/IPricingShim.d.ts +9 -0
- package/dist/pricing-modules/IPricingShim.d.ts.map +1 -0
- package/dist/pricing-modules/IPricingShim.js +9 -0
- package/dist/pricing-modules/IPricingShim.js.map +1 -0
- package/dist/pricing-modules/PricingModules.d.ts +13 -0
- package/dist/pricing-modules/PricingModules.d.ts.map +1 -0
- package/dist/pricing-modules/PricingModules.js +23 -0
- package/dist/pricing-modules/PricingModules.js.map +1 -0
- package/dist/pricing-modules/helpers.d.ts +16 -0
- package/dist/pricing-modules/helpers.d.ts.map +1 -0
- package/dist/pricing-modules/helpers.js +35 -0
- package/dist/pricing-modules/helpers.js.map +1 -0
- package/dist/readContractRetryer.d.ts +10 -0
- package/dist/readContractRetryer.d.ts.map +1 -0
- package/dist/readContractRetryer.js +68 -0
- package/dist/readContractRetryer.js.map +1 -0
- package/dist/river-registry/INodeRegistryShim.d.ts +9 -0
- package/dist/river-registry/INodeRegistryShim.d.ts.map +1 -0
- package/dist/river-registry/INodeRegistryShim.js +9 -0
- package/dist/river-registry/INodeRegistryShim.js.map +1 -0
- package/dist/river-registry/IOperatorRegistryShim.d.ts +9 -0
- package/dist/river-registry/IOperatorRegistryShim.d.ts.map +1 -0
- package/dist/river-registry/IOperatorRegistryShim.js +9 -0
- package/dist/river-registry/IOperatorRegistryShim.js.map +1 -0
- package/dist/river-registry/IStreamRegistryShim.d.ts +9 -0
- package/dist/river-registry/IStreamRegistryShim.d.ts.map +1 -0
- package/dist/river-registry/IStreamRegistryShim.js +9 -0
- package/dist/river-registry/IStreamRegistryShim.js.map +1 -0
- package/dist/river-registry/RiverRegistry.d.ts +18 -0
- package/dist/river-registry/RiverRegistry.d.ts.map +1 -0
- package/dist/river-registry/RiverRegistry.js +42 -0
- package/dist/river-registry/RiverRegistry.js.map +1 -0
- package/dist/river-registry/RiverRegistryFactory.d.ts +5 -0
- package/dist/river-registry/RiverRegistryFactory.d.ts.map +1 -0
- package/dist/river-registry/RiverRegistryFactory.js +5 -0
- package/dist/river-registry/RiverRegistryFactory.js.map +1 -0
- package/dist/space/IAppAccountShim.d.ts +9 -0
- package/dist/space/IAppAccountShim.d.ts.map +1 -0
- package/dist/space/IAppAccountShim.js +9 -0
- package/dist/space/IAppAccountShim.js.map +1 -0
- package/dist/space/IBanningShim.d.ts +9 -0
- package/dist/space/IBanningShim.d.ts.map +1 -0
- package/dist/space/IBanningShim.js +9 -0
- package/dist/space/IBanningShim.js.map +1 -0
- package/dist/space/IChannelShim.d.ts +9 -0
- package/dist/space/IChannelShim.d.ts.map +1 -0
- package/dist/space/IChannelShim.js +9 -0
- package/dist/space/IChannelShim.js.map +1 -0
- package/dist/space/IEntitlementDataQueryableShim.d.ts +11 -0
- package/dist/space/IEntitlementDataQueryableShim.d.ts.map +1 -0
- package/dist/space/IEntitlementDataQueryableShim.js +9 -0
- package/dist/space/IEntitlementDataQueryableShim.js.map +1 -0
- package/dist/space/IEntitlementsShim.d.ts +13 -0
- package/dist/space/IEntitlementsShim.d.ts.map +1 -0
- package/dist/space/IEntitlementsShim.js +19 -0
- package/dist/space/IEntitlementsShim.js.map +1 -0
- package/dist/space/IMembershipMetadataShim.d.ts +9 -0
- package/dist/space/IMembershipMetadataShim.d.ts.map +1 -0
- package/dist/space/IMembershipMetadataShim.js +9 -0
- package/dist/space/IMembershipMetadataShim.js.map +1 -0
- package/dist/space/IMembershipShim.d.ts +33 -0
- package/dist/space/IMembershipShim.d.ts.map +1 -0
- package/dist/space/IMembershipShim.js +139 -0
- package/dist/space/IMembershipShim.js.map +1 -0
- package/dist/space/IMulticallShim.d.ts +13 -0
- package/dist/space/IMulticallShim.d.ts.map +1 -0
- package/dist/space/IMulticallShim.js +15 -0
- package/dist/space/IMulticallShim.js.map +1 -0
- package/dist/space/IReviewShim.d.ts +64 -0
- package/dist/space/IReviewShim.d.ts.map +1 -0
- package/dist/space/IReviewShim.js +102 -0
- package/dist/space/IReviewShim.js.map +1 -0
- package/dist/space/IRolesShim.d.ts +10 -0
- package/dist/space/IRolesShim.d.ts.map +1 -0
- package/dist/space/IRolesShim.js +9 -0
- package/dist/space/IRolesShim.js.map +1 -0
- package/dist/space/ITippingShim.d.ts +39 -0
- package/dist/space/ITippingShim.d.ts.map +1 -0
- package/dist/space/ITippingShim.js +76 -0
- package/dist/space/ITippingShim.js.map +1 -0
- package/dist/space/ITreasuryShim.d.ts +9 -0
- package/dist/space/ITreasuryShim.d.ts.map +1 -0
- package/dist/space/ITreasuryShim.js +9 -0
- package/dist/space/ITreasuryShim.js.map +1 -0
- package/dist/space/OwnableFacetShim.d.ts +12 -0
- package/dist/space/OwnableFacetShim.d.ts.map +1 -0
- package/dist/space/OwnableFacetShim.js +19 -0
- package/dist/space/OwnableFacetShim.js.map +1 -0
- package/dist/space/Space.d.ts +107 -0
- package/dist/space/Space.d.ts.map +1 -0
- package/dist/space/Space.js +511 -0
- package/dist/space/Space.js.map +1 -0
- package/dist/space/TokenPausableFacetShim.d.ts +9 -0
- package/dist/space/TokenPausableFacetShim.d.ts.map +1 -0
- package/dist/space/TokenPausableFacetShim.js +9 -0
- package/dist/space/TokenPausableFacetShim.js.map +1 -0
- package/dist/space/entitlements/ConvertersEntitlements.d.ts +14 -0
- package/dist/space/entitlements/ConvertersEntitlements.d.ts.map +1 -0
- package/dist/space/entitlements/ConvertersEntitlements.js +193 -0
- package/dist/space/entitlements/ConvertersEntitlements.js.map +1 -0
- package/dist/space/entitlements/RuleBuilder.d.ts +83 -0
- package/dist/space/entitlements/RuleBuilder.d.ts.map +1 -0
- package/dist/space/entitlements/RuleBuilder.js +86 -0
- package/dist/space/entitlements/RuleBuilder.js.map +1 -0
- package/dist/space/entitlements/RuleEntitlementShim.d.ts +353 -0
- package/dist/space/entitlements/RuleEntitlementShim.d.ts.map +1 -0
- package/dist/space/entitlements/RuleEntitlementShim.js +40 -0
- package/dist/space/entitlements/RuleEntitlementShim.js.map +1 -0
- package/dist/space/entitlements/RuleEntitlementV2Shim.d.ts +353 -0
- package/dist/space/entitlements/RuleEntitlementV2Shim.d.ts.map +1 -0
- package/dist/space/entitlements/RuleEntitlementV2Shim.js +40 -0
- package/dist/space/entitlements/RuleEntitlementV2Shim.js.map +1 -0
- package/dist/space/entitlements/UserEntitlementShim.d.ts +13 -0
- package/dist/space/entitlements/UserEntitlementShim.d.ts.map +1 -0
- package/dist/space/entitlements/UserEntitlementShim.js +45 -0
- package/dist/space/entitlements/UserEntitlementShim.js.map +1 -0
- package/dist/space/entitlements/XChainConfig.d.ts +14 -0
- package/dist/space/entitlements/XChainConfig.d.ts.map +1 -0
- package/dist/space/entitlements/XChainConfig.js +70 -0
- package/dist/space/entitlements/XChainConfig.js.map +1 -0
- package/dist/space/entitlements/entitlement.d.ts +147 -0
- package/dist/space/entitlements/entitlement.d.ts.map +1 -0
- package/dist/space/entitlements/entitlement.js +940 -0
- package/dist/space/entitlements/entitlement.js.map +1 -0
- package/dist/space/entitlements/validateAndParseXChainConfig.d.ts +6 -0
- package/dist/space/entitlements/validateAndParseXChainConfig.d.ts.map +1 -0
- package/dist/space/entitlements/validateAndParseXChainConfig.js +34 -0
- package/dist/space/entitlements/validateAndParseXChainConfig.js.map +1 -0
- package/dist/space-dapp/SpaceDapp.d.ts +223 -0
- package/dist/space-dapp/SpaceDapp.d.ts.map +1 -0
- package/dist/space-dapp/SpaceDapp.js +1260 -0
- package/dist/space-dapp/SpaceDapp.js.map +1 -0
- package/dist/space-dapp/SpaceDappFactory.d.ts +5 -0
- package/dist/space-dapp/SpaceDappFactory.d.ts.map +1 -0
- package/dist/space-dapp/SpaceDappFactory.js +8 -0
- package/dist/space-dapp/SpaceDappFactory.js.map +1 -0
- package/dist/space-dapp/wrapTransaction.d.ts +4 -0
- package/dist/space-dapp/wrapTransaction.d.ts.map +1 -0
- package/dist/space-dapp/wrapTransaction.js +99 -0
- package/dist/space-dapp/wrapTransaction.js.map +1 -0
- package/dist/space-owner/GuardianFacetShim.d.ts +9 -0
- package/dist/space-owner/GuardianFacetShim.d.ts.map +1 -0
- package/dist/space-owner/GuardianFacetShim.js +9 -0
- package/dist/space-owner/GuardianFacetShim.js.map +1 -0
- package/dist/space-owner/SpaceOwner.d.ts +48 -0
- package/dist/space-owner/SpaceOwner.d.ts.map +1 -0
- package/dist/space-owner/SpaceOwner.js +81 -0
- package/dist/space-owner/SpaceOwner.js.map +1 -0
- package/dist/space-registrar/ICreateSpaceShim.d.ts +11 -0
- package/dist/space-registrar/ICreateSpaceShim.d.ts.map +1 -0
- package/dist/space-registrar/ICreateSpaceShim.js +9 -0
- package/dist/space-registrar/ICreateSpaceShim.js.map +1 -0
- package/dist/space-registrar/ILegacySpaceArchitectShim.d.ts +10 -0
- package/dist/space-registrar/ILegacySpaceArchitectShim.d.ts.map +1 -0
- package/dist/space-registrar/ILegacySpaceArchitectShim.js +9 -0
- package/dist/space-registrar/ILegacySpaceArchitectShim.js.map +1 -0
- package/dist/space-registrar/ISpaceArchitectShim.d.ts +10 -0
- package/dist/space-registrar/ISpaceArchitectShim.d.ts.map +1 -0
- package/dist/space-registrar/ISpaceArchitectShim.js +39 -0
- package/dist/space-registrar/ISpaceArchitectShim.js.map +1 -0
- package/dist/space-registrar/SpaceRegistrar.d.ts +27 -0
- package/dist/space-registrar/SpaceRegistrar.d.ts.map +1 -0
- package/dist/space-registrar/SpaceRegistrar.js +58 -0
- package/dist/space-registrar/SpaceRegistrar.js.map +1 -0
- package/dist/test-helpers/LocalhostWeb3Provider.d.ts +19 -0
- package/dist/test-helpers/LocalhostWeb3Provider.d.ts.map +1 -0
- package/dist/test-helpers/LocalhostWeb3Provider.js +80 -0
- package/dist/test-helpers/LocalhostWeb3Provider.js.map +1 -0
- package/dist/test-helpers/MockCrossChainEntitlement.d.ts +6 -0
- package/dist/test-helpers/MockCrossChainEntitlement.d.ts.map +1 -0
- package/dist/test-helpers/MockCrossChainEntitlement.js +104 -0
- package/dist/test-helpers/MockCrossChainEntitlement.js.map +1 -0
- package/dist/test-helpers/MockERC1155.d.ts +6 -0
- package/dist/test-helpers/MockERC1155.d.ts.map +1 -0
- package/dist/test-helpers/MockERC1155.js +518 -0
- package/dist/test-helpers/MockERC1155.js.map +1 -0
- package/dist/test-helpers/MockERC20.d.ts +6 -0
- package/dist/test-helpers/MockERC20.d.ts.map +1 -0
- package/dist/test-helpers/MockERC20.js +574 -0
- package/dist/test-helpers/MockERC20.js.map +1 -0
- package/dist/test-helpers/MockERC721A.d.ts +1563 -0
- package/dist/test-helpers/MockERC721A.d.ts.map +1 -0
- package/dist/test-helpers/MockERC721A.js +1913 -0
- package/dist/test-helpers/MockERC721A.js.map +1 -0
- package/dist/test-helpers/MockERC721AShim.d.ts +9 -0
- package/dist/test-helpers/MockERC721AShim.d.ts.map +1 -0
- package/dist/test-helpers/MockERC721AShim.js +9 -0
- package/dist/test-helpers/MockERC721AShim.js.map +1 -0
- package/dist/test-helpers/TestCrossChainEntitlement.d.ts +14 -0
- package/dist/test-helpers/TestCrossChainEntitlement.d.ts.map +1 -0
- package/dist/test-helpers/TestCrossChainEntitlement.js +99 -0
- package/dist/test-helpers/TestCrossChainEntitlement.js.map +1 -0
- package/dist/test-helpers/TestEthBalance.d.ts +72 -0
- package/dist/test-helpers/TestEthBalance.d.ts.map +1 -0
- package/dist/test-helpers/TestEthBalance.js +94 -0
- package/dist/test-helpers/TestEthBalance.js.map +1 -0
- package/dist/test-helpers/TestGatingERC1155.d.ts +17 -0
- package/dist/test-helpers/TestGatingERC1155.d.ts.map +1 -0
- package/dist/test-helpers/TestGatingERC1155.js +100 -0
- package/dist/test-helpers/TestGatingERC1155.js.map +1 -0
- package/dist/test-helpers/TestGatingERC20.d.ts +17 -0
- package/dist/test-helpers/TestGatingERC20.d.ts.map +1 -0
- package/dist/test-helpers/TestGatingERC20.js +149 -0
- package/dist/test-helpers/TestGatingERC20.js.map +1 -0
- package/dist/test-helpers/TestGatingNFT.d.ts +17 -0
- package/dist/test-helpers/TestGatingNFT.d.ts.map +1 -0
- package/dist/test-helpers/TestGatingNFT.js +137 -0
- package/dist/test-helpers/TestGatingNFT.js.map +1 -0
- package/dist/test-helpers/TestGatingUtils.d.ts +15 -0
- package/dist/test-helpers/TestGatingUtils.d.ts.map +1 -0
- package/dist/test-helpers/TestGatingUtils.js +112 -0
- package/dist/test-helpers/TestGatingUtils.js.map +1 -0
- package/dist/test-helpers/utils.d.ts +22 -0
- package/dist/test-helpers/utils.d.ts.map +1 -0
- package/dist/test-helpers/utils.js +30 -0
- package/dist/test-helpers/utils.js.map +1 -0
- package/dist/towns-token/TownsToken.d.ts +17 -0
- package/dist/towns-token/TownsToken.d.ts.map +1 -0
- package/dist/towns-token/TownsToken.js +33 -0
- package/dist/towns-token/TownsToken.js.map +1 -0
- package/dist/types/ContractTypes.d.ts +240 -0
- package/dist/types/ContractTypes.d.ts.map +1 -0
- package/dist/types/ContractTypes.js +65 -0
- package/dist/types/ContractTypes.js.map +1 -0
- package/dist/types/error-types.d.ts +7 -0
- package/dist/types/error-types.d.ts.map +1 -0
- package/dist/types/error-types.js +13 -0
- package/dist/types/error-types.js.map +1 -0
- package/dist/types/typechain.d.ts +4 -0
- package/dist/types/typechain.d.ts.map +1 -0
- package/dist/types/typechain.js +2 -0
- package/dist/types/typechain.js.map +1 -0
- package/dist/types/types.d.ts +29 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +2 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/ContractHelpers.d.ts +14 -0
- package/dist/utils/ContractHelpers.d.ts.map +1 -0
- package/dist/utils/ContractHelpers.js +54 -0
- package/dist/utils/ContractHelpers.js.map +1 -0
- package/dist/utils/Web3Constants.d.ts +6 -0
- package/dist/utils/Web3Constants.d.ts.map +1 -0
- package/dist/utils/Web3Constants.js +7 -0
- package/dist/utils/Web3Constants.js.map +1 -0
- package/dist/utils/ut.d.ts +46 -0
- package/dist/utils/ut.d.ts.map +1 -0
- package/dist/utils/ut.js +94 -0
- package/dist/utils/ut.js.map +1 -0
- package/dist/utils/web3Env.d.ts +36 -0
- package/dist/utils/web3Env.d.ts.map +1 -0
- package/dist/utils/web3Env.js +123 -0
- package/dist/utils/web3Env.js.map +1 -0
- package/dist/wallet-link/WalletLink.d.ts +58 -0
- package/dist/wallet-link/WalletLink.d.ts.map +1 -0
- package/dist/wallet-link/WalletLink.js +226 -0
- package/dist/wallet-link/WalletLink.js.map +1 -0
- package/dist/wallet-link/WalletLinkShim.d.ts +9 -0
- package/dist/wallet-link/WalletLinkShim.d.ts.map +1 -0
- package/dist/wallet-link/WalletLinkShim.js +9 -0
- package/dist/wallet-link/WalletLinkShim.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,1260 @@
|
|
|
1
|
+
import { EntitlementModuleType, isPermission, isUpdateChannelStatusParams, Permission, } from '../types/ContractTypes';
|
|
2
|
+
import { computeDelegatorsForProvider } from '../delegate-registry/DelegateRegistry';
|
|
3
|
+
import { ethers } from 'ethers';
|
|
4
|
+
import { LOCALHOST_CHAIN_ID } from '../utils/Web3Constants';
|
|
5
|
+
import { EVERYONE_ADDRESS, stringifyChannelMetadataJSON, NoEntitledWalletError, ETH_ADDRESS, } from '../utils/ut';
|
|
6
|
+
import { SpaceRegistrar } from '../space-registrar/SpaceRegistrar';
|
|
7
|
+
import { evaluateOperationsForEntitledWallet, ruleDataToOperations, findEthereumProviders, } from '../space/entitlements/entitlement';
|
|
8
|
+
import { createEntitlementStruct, createLegacyEntitlementStruct, convertRuleDataV1ToV2, } from '../space/entitlements/ConvertersEntitlements';
|
|
9
|
+
import { RiverAirdropDapp } from '../airdrop/RiverAirdropDapp';
|
|
10
|
+
import { WalletLink, INVALID_ADDRESS } from '../wallet-link/WalletLink';
|
|
11
|
+
import { UNKNOWN_ERROR } from '../BaseContractShim';
|
|
12
|
+
import { PricingModules } from '../pricing-modules/PricingModules';
|
|
13
|
+
import { dlogger, isTestEnv } from '@towns-labs/utils';
|
|
14
|
+
import { PlatformRequirements } from '../platform-requirements/PlatformRequirements';
|
|
15
|
+
import { EntitlementCache } from '../cache/EntitlementCache';
|
|
16
|
+
import { SimpleCache } from '../cache/SimpleCache';
|
|
17
|
+
import { ITippingShim } from '../space/ITippingShim';
|
|
18
|
+
import { SpaceOwner } from '../space-owner/SpaceOwner';
|
|
19
|
+
import { TownsToken } from '../towns-token/TownsToken';
|
|
20
|
+
import { wrapTransaction } from '../space-dapp/wrapTransaction';
|
|
21
|
+
import { BaseRegistry } from '../base-registry/BaseRegistry';
|
|
22
|
+
import { Keyable } from '../cache/Keyable';
|
|
23
|
+
const logger = dlogger('csb:SpaceDapp:debug');
|
|
24
|
+
class EntitlementDataCacheResult {
|
|
25
|
+
value;
|
|
26
|
+
cacheHit;
|
|
27
|
+
isPositive;
|
|
28
|
+
constructor(value) {
|
|
29
|
+
this.value = value;
|
|
30
|
+
this.cacheHit = false;
|
|
31
|
+
this.isPositive = true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
class EntitledWalletCacheResult {
|
|
35
|
+
value;
|
|
36
|
+
cacheHit;
|
|
37
|
+
isPositive;
|
|
38
|
+
constructor(value) {
|
|
39
|
+
this.value = value;
|
|
40
|
+
this.cacheHit = false;
|
|
41
|
+
this.isPositive = value !== undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
class BooleanCacheResult {
|
|
45
|
+
value;
|
|
46
|
+
cacheHit;
|
|
47
|
+
isPositive;
|
|
48
|
+
constructor(value) {
|
|
49
|
+
this.value = value;
|
|
50
|
+
this.cacheHit = false;
|
|
51
|
+
this.isPositive = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function ensureHexPrefix(value) {
|
|
55
|
+
return value.startsWith('0x') ? value : `0x${value}`;
|
|
56
|
+
}
|
|
57
|
+
const EmptyXchainConfig = {
|
|
58
|
+
supportedRpcUrls: {},
|
|
59
|
+
etherNativeNetworkIds: [],
|
|
60
|
+
ethereumNetworkIds: [],
|
|
61
|
+
};
|
|
62
|
+
export class SpaceDapp {
|
|
63
|
+
isLegacySpaceCache;
|
|
64
|
+
config;
|
|
65
|
+
baseRegistry;
|
|
66
|
+
provider;
|
|
67
|
+
spaceRegistrar;
|
|
68
|
+
pricingModules;
|
|
69
|
+
walletLink;
|
|
70
|
+
platformRequirements;
|
|
71
|
+
airdrop;
|
|
72
|
+
spaceOwner;
|
|
73
|
+
townsToken;
|
|
74
|
+
entitlementCache;
|
|
75
|
+
entitledWalletCache;
|
|
76
|
+
entitlementEvaluationCache;
|
|
77
|
+
bannedTokenIdsCache;
|
|
78
|
+
ownerOfTokenCache;
|
|
79
|
+
isBannedTokenCache;
|
|
80
|
+
constructor(config, provider, createStorageFn) {
|
|
81
|
+
this.isLegacySpaceCache = new Map();
|
|
82
|
+
this.config = config;
|
|
83
|
+
this.provider = provider;
|
|
84
|
+
this.baseRegistry = new BaseRegistry(config, provider);
|
|
85
|
+
this.spaceRegistrar = new SpaceRegistrar(config, provider, createStorageFn);
|
|
86
|
+
this.walletLink = new WalletLink(config, provider);
|
|
87
|
+
this.pricingModules = new PricingModules(config, provider);
|
|
88
|
+
this.platformRequirements = new PlatformRequirements(config.addresses.spaceFactory, provider);
|
|
89
|
+
this.spaceOwner = new SpaceOwner(config.addresses.spaceOwner, provider, createStorageFn);
|
|
90
|
+
if (config.addresses.utils.towns) {
|
|
91
|
+
this.townsToken = new TownsToken(config.addresses.utils.towns, provider, createStorageFn);
|
|
92
|
+
}
|
|
93
|
+
this.airdrop = new RiverAirdropDapp(config, provider);
|
|
94
|
+
// For RPC providers that pool for events, we need to set the polling interval to a lower value
|
|
95
|
+
// so that we don't miss events that may be emitted in between polling intervals. The Ethers
|
|
96
|
+
// default is 4000ms, which is based on the assumption of 12s mainnet blocktimes.
|
|
97
|
+
if ('pollingInterval' in provider && typeof provider.pollingInterval === 'number') {
|
|
98
|
+
provider.pollingInterval = 250;
|
|
99
|
+
}
|
|
100
|
+
const isLocalDev = isTestEnv() || config.chainId === LOCALHOST_CHAIN_ID;
|
|
101
|
+
const entitlementCacheOpts = {
|
|
102
|
+
positiveCacheTTLSeconds: isLocalDev ? 5 : 15 * 60,
|
|
103
|
+
negativeCacheTTLSeconds: 2,
|
|
104
|
+
createStorageFn,
|
|
105
|
+
};
|
|
106
|
+
const bannedCacheOpts = {
|
|
107
|
+
ttlSeconds: isLocalDev ? 5 : 15 * 60,
|
|
108
|
+
createStorageFn,
|
|
109
|
+
};
|
|
110
|
+
// The caching of positive entitlements is shorter on both the node and client.
|
|
111
|
+
this.entitlementCache = new EntitlementCache({
|
|
112
|
+
positiveCacheTTLSeconds: isLocalDev ? 5 : 15,
|
|
113
|
+
negativeCacheTTLSeconds: 2,
|
|
114
|
+
createStorageFn,
|
|
115
|
+
});
|
|
116
|
+
this.entitledWalletCache = new EntitlementCache({
|
|
117
|
+
...entitlementCacheOpts,
|
|
118
|
+
});
|
|
119
|
+
this.entitlementEvaluationCache = new EntitlementCache({
|
|
120
|
+
...entitlementCacheOpts,
|
|
121
|
+
});
|
|
122
|
+
this.bannedTokenIdsCache = new SimpleCache({
|
|
123
|
+
...bannedCacheOpts,
|
|
124
|
+
});
|
|
125
|
+
this.ownerOfTokenCache = new SimpleCache({
|
|
126
|
+
...bannedCacheOpts,
|
|
127
|
+
});
|
|
128
|
+
this.isBannedTokenCache = new SimpleCache({
|
|
129
|
+
...bannedCacheOpts,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async isLegacySpace(spaceId) {
|
|
133
|
+
const cachedValue = this.isLegacySpaceCache.get(spaceId);
|
|
134
|
+
if (cachedValue !== undefined) {
|
|
135
|
+
return cachedValue;
|
|
136
|
+
}
|
|
137
|
+
const space = this.getSpace(spaceId);
|
|
138
|
+
if (!space) {
|
|
139
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
140
|
+
}
|
|
141
|
+
// Legacy spaces do not have RuleEntitlementV2
|
|
142
|
+
const maybeShim = await space.findEntitlementByType(EntitlementModuleType.RuleEntitlementV2);
|
|
143
|
+
const isLegacy = maybeShim === null;
|
|
144
|
+
this.isLegacySpaceCache.set(spaceId, isLegacy);
|
|
145
|
+
return isLegacy;
|
|
146
|
+
}
|
|
147
|
+
async addRoleToChannel(spaceId, channelNetworkId, roleId, signer, txnOpts) {
|
|
148
|
+
const space = this.getSpace(spaceId);
|
|
149
|
+
if (!space) {
|
|
150
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
151
|
+
}
|
|
152
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
153
|
+
return wrapTransaction(() => space.Channels.write(signer).addRoleToChannel(channelId, roleId), txnOpts);
|
|
154
|
+
}
|
|
155
|
+
async banWalletAddress(spaceId, walletAddress, signer, txnOpts) {
|
|
156
|
+
const space = this.getSpace(spaceId);
|
|
157
|
+
if (!space) {
|
|
158
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
159
|
+
}
|
|
160
|
+
const token = await space.ERC721AQueryable.read
|
|
161
|
+
.tokensOfOwner(walletAddress)
|
|
162
|
+
.then((tokens) => tokens.at(0));
|
|
163
|
+
if (!token) {
|
|
164
|
+
throw new Error(`Wallet address "${walletAddress}" is not a member of space "${spaceId}".`);
|
|
165
|
+
}
|
|
166
|
+
// Call ban
|
|
167
|
+
const tx = await wrapTransaction(() => space.Banning.write(signer).ban(token), txnOpts);
|
|
168
|
+
await this.updateCacheAfterBanOrUnBan(spaceId, token);
|
|
169
|
+
return tx;
|
|
170
|
+
}
|
|
171
|
+
async unbanWalletAddress(spaceId, walletAddress, signer, txnOpts) {
|
|
172
|
+
const space = this.getSpace(spaceId);
|
|
173
|
+
if (!space) {
|
|
174
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
175
|
+
}
|
|
176
|
+
const token = await space.ERC721AQueryable.read
|
|
177
|
+
.tokensOfOwner(walletAddress)
|
|
178
|
+
.then((tokens) => tokens.at(0));
|
|
179
|
+
if (!token) {
|
|
180
|
+
throw new Error(`Wallet address "${walletAddress}" is not a member of space "${spaceId}".`);
|
|
181
|
+
}
|
|
182
|
+
// Call unban
|
|
183
|
+
const tx = await wrapTransaction(() => space.Banning.write(signer).unban(token), txnOpts);
|
|
184
|
+
await this.updateCacheAfterBanOrUnBan(spaceId, token);
|
|
185
|
+
return tx;
|
|
186
|
+
}
|
|
187
|
+
async updateCacheAfterBanOrUnBan(spaceId, tokenId) {
|
|
188
|
+
await Promise.all([
|
|
189
|
+
this.bannedTokenIdsCache.remove(Keyable.bannedTokenIds(spaceId)),
|
|
190
|
+
this.ownerOfTokenCache.remove(Keyable.ownerOfToken(spaceId, tokenId)),
|
|
191
|
+
this.isBannedTokenCache.remove(Keyable.isTokenBanned(spaceId, tokenId)),
|
|
192
|
+
]);
|
|
193
|
+
}
|
|
194
|
+
async walletAddressIsBanned(spaceId, walletAddress, opts) {
|
|
195
|
+
const space = this.getSpace(spaceId);
|
|
196
|
+
if (!space) {
|
|
197
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
198
|
+
}
|
|
199
|
+
const tokenId = await space.ERC721AQueryable.read
|
|
200
|
+
.tokensOfOwner(walletAddress)
|
|
201
|
+
.then((tokens) => tokens.at(0));
|
|
202
|
+
if (!tokenId) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
const isBanned = await this.isBannedTokenCache.executeUsingCache(Keyable.isTokenBanned(spaceId, tokenId), async () => space.Banning.read.isBanned(tokenId), opts);
|
|
206
|
+
return isBanned;
|
|
207
|
+
}
|
|
208
|
+
async bannedWalletAddresses(spaceId) {
|
|
209
|
+
const space = this.getSpace(spaceId);
|
|
210
|
+
if (!space) {
|
|
211
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
212
|
+
}
|
|
213
|
+
// 1. Get banned token IDs
|
|
214
|
+
const bannedTokenIds = await this.bannedTokenIdsCache.executeUsingCache(Keyable.bannedTokenIds(spaceId), async () => {
|
|
215
|
+
const currentSpace = this.getSpace(spaceId);
|
|
216
|
+
if (!currentSpace) {
|
|
217
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found inside cache fetch.`);
|
|
218
|
+
}
|
|
219
|
+
return currentSpace.Banning.read.banned();
|
|
220
|
+
});
|
|
221
|
+
// 2. Get owner for each banned token ID using cache and multicall for efficiency
|
|
222
|
+
const ownerMap = new Map(); // tokenId.toString() -> ownerAddress
|
|
223
|
+
const tokenIdsToFetch = [];
|
|
224
|
+
// Check cache first - parallel lookups for remote storage efficiency
|
|
225
|
+
const cacheResults = await Promise.all(bannedTokenIds.map(async (tokenId) => {
|
|
226
|
+
const cacheKey = Keyable.ownerOfToken(spaceId, tokenId);
|
|
227
|
+
const cachedOwner = await this.ownerOfTokenCache.get(cacheKey);
|
|
228
|
+
return { tokenId, cachedOwner };
|
|
229
|
+
}));
|
|
230
|
+
for (const { tokenId, cachedOwner } of cacheResults) {
|
|
231
|
+
if (cachedOwner) {
|
|
232
|
+
ownerMap.set(tokenId.toString(), cachedOwner);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
tokenIdsToFetch.push(tokenId);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
// Fetch non-cached owners
|
|
239
|
+
if (tokenIdsToFetch.length > 0 && space) {
|
|
240
|
+
const calls = tokenIdsToFetch.map((tokenId) => space.ERC721A.interface.encodeFunctionData('ownerOf', [tokenId]));
|
|
241
|
+
try {
|
|
242
|
+
const results = await space.Multicall.read.callStatic.multicall(calls);
|
|
243
|
+
const cacheWritePromises = [];
|
|
244
|
+
for (const [index, resultData] of results.entries()) {
|
|
245
|
+
const tokenId = tokenIdsToFetch[index];
|
|
246
|
+
// Attempt to decode each result
|
|
247
|
+
try {
|
|
248
|
+
if (resultData && resultData !== '0x') {
|
|
249
|
+
const ownerAddress = space.ERC721A.interface.decodeFunctionResult('ownerOf', resultData)[0];
|
|
250
|
+
if (ethers.utils.isAddress(ownerAddress)) {
|
|
251
|
+
ownerMap.set(tokenId.toString(), ownerAddress);
|
|
252
|
+
// Collect cache write promises for parallel execution
|
|
253
|
+
cacheWritePromises.push(this.ownerOfTokenCache.add(Keyable.ownerOfToken(spaceId, tokenId), ownerAddress));
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
logger.log(`bannedWalletAddresses: Multicall: Decoded ownerOf result is not a valid address for token ${tokenId.toString()} in space ${spaceId}: ${ownerAddress}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
logger.log(`bannedWalletAddresses: Multicall: ownerOf call returned empty data for token ${tokenId.toString()} in space ${spaceId}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch (decodeError) {
|
|
264
|
+
logger.error(`bannedWalletAddresses: Multicall: Failed to decode ownerOf result for token ${tokenId.toString()} in space ${spaceId}`, decodeError instanceof Error
|
|
265
|
+
? decodeError.message
|
|
266
|
+
: String(decodeError));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Write all cache entries in parallel
|
|
270
|
+
await Promise.all(cacheWritePromises);
|
|
271
|
+
}
|
|
272
|
+
catch (multiCallError) {
|
|
273
|
+
logger.error(`Multicall execution failed for space ${spaceId}. This likely means one of the ownerOf calls reverted.`, multiCallError instanceof Error
|
|
274
|
+
? multiCallError.message
|
|
275
|
+
: String(multiCallError));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Return the unique owner addresses combined from cache and multicall
|
|
279
|
+
return Array.from(new Set(ownerMap.values()));
|
|
280
|
+
}
|
|
281
|
+
async createLegacySpace(params, signer, txnOpts) {
|
|
282
|
+
const spaceInfo = {
|
|
283
|
+
name: params.spaceName,
|
|
284
|
+
uri: params.uri,
|
|
285
|
+
membership: params.membership,
|
|
286
|
+
channel: {
|
|
287
|
+
metadata: params.channelName || '',
|
|
288
|
+
},
|
|
289
|
+
shortDescription: params.shortDescription ?? '',
|
|
290
|
+
longDescription: params.longDescription ?? '',
|
|
291
|
+
};
|
|
292
|
+
return wrapTransaction(() => this.spaceRegistrar.LegacySpaceArchitect.write(signer).createSpace(spaceInfo), txnOpts);
|
|
293
|
+
}
|
|
294
|
+
async createSpace(params, signer, txnOpts) {
|
|
295
|
+
return wrapTransaction(() => {
|
|
296
|
+
const createSpaceFunction = this.spaceRegistrar.CreateSpace.write(signer)['createSpace((string,string,string,string,((string,string,uint256,uint256,uint64,address,address,uint256,address),(bool,address[],bytes,bool),string[]),(string)))'];
|
|
297
|
+
return createSpaceFunction({
|
|
298
|
+
name: params.spaceName,
|
|
299
|
+
uri: params.uri,
|
|
300
|
+
shortDescription: params.shortDescription || '',
|
|
301
|
+
longDescription: params.longDescription || '',
|
|
302
|
+
membership: params.membership,
|
|
303
|
+
channel: {
|
|
304
|
+
metadata: params.channelName || '',
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
}, txnOpts);
|
|
308
|
+
}
|
|
309
|
+
async createChannel(spaceId, channelName, channelDescription, channelNetworkId, roleIds, signer, txnOpts) {
|
|
310
|
+
const space = this.getSpace(spaceId);
|
|
311
|
+
if (!space) {
|
|
312
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
313
|
+
}
|
|
314
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
315
|
+
return wrapTransaction(() => space.Channels.write(signer).createChannel(channelId, stringifyChannelMetadataJSON({
|
|
316
|
+
name: channelName,
|
|
317
|
+
description: channelDescription,
|
|
318
|
+
}), roleIds), txnOpts);
|
|
319
|
+
}
|
|
320
|
+
async createChannelWithPermissionOverrides(spaceId, channelName, channelDescription, channelNetworkId, roles, signer, txnOpts) {
|
|
321
|
+
const space = this.getSpace(spaceId);
|
|
322
|
+
if (!space) {
|
|
323
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
324
|
+
}
|
|
325
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
326
|
+
return wrapTransaction(() => space.Channels.write(signer).createChannelWithOverridePermissions(channelId, stringifyChannelMetadataJSON({
|
|
327
|
+
name: channelName,
|
|
328
|
+
description: channelDescription,
|
|
329
|
+
}), roles), txnOpts);
|
|
330
|
+
}
|
|
331
|
+
async legacyCreateRole(spaceId, roleName, permissions, users, ruleData, signer, txnOpts) {
|
|
332
|
+
const space = this.getSpace(spaceId);
|
|
333
|
+
if (!space) {
|
|
334
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
335
|
+
}
|
|
336
|
+
const entitlements = await createLegacyEntitlementStruct(space, users, ruleData);
|
|
337
|
+
return wrapTransaction(() => space.Roles.write(signer).createRole(roleName, permissions, entitlements), txnOpts);
|
|
338
|
+
}
|
|
339
|
+
async createRole(spaceId, roleName, permissions, users, ruleData, signer, txnOpts) {
|
|
340
|
+
const space = this.getSpace(spaceId);
|
|
341
|
+
if (!space) {
|
|
342
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
343
|
+
}
|
|
344
|
+
const entitlements = await createEntitlementStruct(space, users, ruleData);
|
|
345
|
+
return wrapTransaction(() => space.Roles.write(signer).createRole(roleName, permissions, entitlements), txnOpts);
|
|
346
|
+
}
|
|
347
|
+
async deleteRole(spaceId, roleId, signer, txnOpts) {
|
|
348
|
+
const space = this.getSpace(spaceId);
|
|
349
|
+
if (!space) {
|
|
350
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
351
|
+
}
|
|
352
|
+
return wrapTransaction(() => space.Roles.write(signer).removeRole(roleId), txnOpts);
|
|
353
|
+
}
|
|
354
|
+
async getChannels(spaceId) {
|
|
355
|
+
const space = this.getSpace(spaceId);
|
|
356
|
+
if (!space) {
|
|
357
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
358
|
+
}
|
|
359
|
+
return space.getChannels();
|
|
360
|
+
}
|
|
361
|
+
async getChannelDetails(spaceId, channelNetworkId) {
|
|
362
|
+
const space = this.getSpace(spaceId);
|
|
363
|
+
if (!space) {
|
|
364
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
365
|
+
}
|
|
366
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
367
|
+
return space.getChannel(channelId);
|
|
368
|
+
}
|
|
369
|
+
async getPermissionsByRoleId(spaceId, roleId) {
|
|
370
|
+
const space = this.getSpace(spaceId);
|
|
371
|
+
if (!space) {
|
|
372
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
373
|
+
}
|
|
374
|
+
return space.getPermissionsByRoleId(roleId);
|
|
375
|
+
}
|
|
376
|
+
async getRole(spaceId, roleId) {
|
|
377
|
+
const space = this.getSpace(spaceId);
|
|
378
|
+
if (!space) {
|
|
379
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
380
|
+
}
|
|
381
|
+
return space.getRole(roleId);
|
|
382
|
+
}
|
|
383
|
+
async getRoles(spaceId) {
|
|
384
|
+
const space = this.getSpace(spaceId);
|
|
385
|
+
if (!space) {
|
|
386
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
387
|
+
}
|
|
388
|
+
const roles = await space.Roles.read.getRoles();
|
|
389
|
+
return roles.map((role) => ({
|
|
390
|
+
roleId: role.id.toNumber(),
|
|
391
|
+
name: role.name,
|
|
392
|
+
}));
|
|
393
|
+
}
|
|
394
|
+
async getSpaceInfo(spaceId) {
|
|
395
|
+
const space = this.getSpace(spaceId);
|
|
396
|
+
if (!space) {
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
const [owner, disabled, spaceInfo] = await Promise.all([
|
|
400
|
+
space.Ownable.getOwner(),
|
|
401
|
+
space.Pausable.read.paused(),
|
|
402
|
+
this.spaceOwner.getSpaceInfo(space.Address),
|
|
403
|
+
]);
|
|
404
|
+
return {
|
|
405
|
+
address: space.Address,
|
|
406
|
+
networkId: space.SpaceId,
|
|
407
|
+
name: spaceInfo.name ?? '',
|
|
408
|
+
owner,
|
|
409
|
+
disabled,
|
|
410
|
+
uri: spaceInfo.uri ?? '',
|
|
411
|
+
tokenId: ethers.BigNumber.from(spaceInfo.tokenId).toString(),
|
|
412
|
+
createdAt: ethers.BigNumber.from(spaceInfo.createdAt).toString(),
|
|
413
|
+
shortDescription: spaceInfo.shortDescription ?? '',
|
|
414
|
+
longDescription: spaceInfo.longDescription ?? '',
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
async decodeEntitlementData(space, entitlementData) {
|
|
418
|
+
const entitlements = entitlementData.map((x) => ({
|
|
419
|
+
entitlementType: x.entitlementType,
|
|
420
|
+
ruleEntitlement: undefined,
|
|
421
|
+
userEntitlement: undefined,
|
|
422
|
+
}));
|
|
423
|
+
const [userEntitlementShim, ruleEntitlementShim, ruleEntitlementV2Shim] = (await Promise.all([
|
|
424
|
+
space.findEntitlementByType(EntitlementModuleType.UserEntitlement),
|
|
425
|
+
space.findEntitlementByType(EntitlementModuleType.RuleEntitlement),
|
|
426
|
+
space.findEntitlementByType(EntitlementModuleType.RuleEntitlementV2),
|
|
427
|
+
]));
|
|
428
|
+
for (let i = 0; i < entitlementData.length; i++) {
|
|
429
|
+
const entitlement = entitlementData[i];
|
|
430
|
+
if (entitlement.entitlementType ===
|
|
431
|
+
EntitlementModuleType.RuleEntitlement) {
|
|
432
|
+
if (ruleEntitlementShim)
|
|
433
|
+
entitlements[i].entitlementType = EntitlementModuleType.RuleEntitlement;
|
|
434
|
+
const decodedData = ruleEntitlementShim?.decodeGetRuleData(entitlement.entitlementData);
|
|
435
|
+
if (decodedData) {
|
|
436
|
+
entitlements[i].ruleEntitlement = {
|
|
437
|
+
kind: 'v1',
|
|
438
|
+
rules: decodedData,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
else if (entitlement.entitlementType ===
|
|
443
|
+
EntitlementModuleType.RuleEntitlementV2) {
|
|
444
|
+
entitlements[i].entitlementType = EntitlementModuleType.RuleEntitlementV2;
|
|
445
|
+
const decodedData = ruleEntitlementV2Shim?.decodeGetRuleData(entitlement.entitlementData);
|
|
446
|
+
if (decodedData) {
|
|
447
|
+
entitlements[i].ruleEntitlement = {
|
|
448
|
+
kind: 'v2',
|
|
449
|
+
rules: decodedData,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
else if (entitlement.entitlementType ===
|
|
454
|
+
EntitlementModuleType.UserEntitlement) {
|
|
455
|
+
entitlements[i].entitlementType = EntitlementModuleType.UserEntitlement;
|
|
456
|
+
const decodedData = userEntitlementShim?.decodeGetAddresses(entitlement.entitlementData);
|
|
457
|
+
if (decodedData) {
|
|
458
|
+
entitlements[i].userEntitlement = decodedData;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
throw new Error('Unknown entitlement type');
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return entitlements;
|
|
466
|
+
}
|
|
467
|
+
async getEntitlementsForPermission(spaceId, permission) {
|
|
468
|
+
const { value } = await this.entitlementCache.executeUsingCache(Keyable.spaceEntitlement(spaceId, permission), async () => {
|
|
469
|
+
const entitlementData = await this.getEntitlementsForPermissionUncached(spaceId, permission);
|
|
470
|
+
return new EntitlementDataCacheResult(entitlementData);
|
|
471
|
+
});
|
|
472
|
+
return value;
|
|
473
|
+
}
|
|
474
|
+
async getEntitlementsForPermissionUncached(spaceId, permission) {
|
|
475
|
+
const space = this.getSpace(spaceId);
|
|
476
|
+
if (!space) {
|
|
477
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
478
|
+
}
|
|
479
|
+
const entitlementData = await space.EntitlementDataQueryable.read.getEntitlementDataByPermission(permission);
|
|
480
|
+
return await this.decodeEntitlementData(space, entitlementData);
|
|
481
|
+
}
|
|
482
|
+
async getChannelEntitlementsForPermission(spaceId, channelId, permission) {
|
|
483
|
+
const { value } = await this.entitlementCache.executeUsingCache(Keyable.channelEntitlement(spaceId, channelId, permission), async () => {
|
|
484
|
+
const entitlementData = await this.getChannelEntitlementsForPermissionUncached(spaceId, channelId, permission);
|
|
485
|
+
return new EntitlementDataCacheResult(entitlementData);
|
|
486
|
+
});
|
|
487
|
+
return value;
|
|
488
|
+
}
|
|
489
|
+
async getChannelEntitlementsForPermissionUncached(spaceId, channelId, permission) {
|
|
490
|
+
const space = this.getSpace(spaceId);
|
|
491
|
+
if (!space) {
|
|
492
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
493
|
+
}
|
|
494
|
+
const entitlementData = await space.EntitlementDataQueryable.read.getChannelEntitlementDataByPermission(channelId, permission);
|
|
495
|
+
return await this.decodeEntitlementData(space, entitlementData);
|
|
496
|
+
}
|
|
497
|
+
async getLinkedWallets(wallet) {
|
|
498
|
+
let linkedWallets = await this.walletLink.getLinkedWallets(wallet);
|
|
499
|
+
// If there are no linked wallets, consider that the wallet may be linked to another root key.
|
|
500
|
+
if (linkedWallets.length === 0) {
|
|
501
|
+
const possibleRoot = await this.walletLink.getRootKeyForWallet(wallet);
|
|
502
|
+
if (possibleRoot !== INVALID_ADDRESS) {
|
|
503
|
+
linkedWallets = await this.walletLink.getLinkedWallets(possibleRoot);
|
|
504
|
+
return [possibleRoot, ...linkedWallets];
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return [wallet, ...linkedWallets];
|
|
508
|
+
}
|
|
509
|
+
async getMainnetDelegationsForLinkedWallets(linkedWallets, config) {
|
|
510
|
+
const delegatorSet = new Set();
|
|
511
|
+
const ethProviders = await findEthereumProviders(config);
|
|
512
|
+
for (const provider of ethProviders) {
|
|
513
|
+
const delegators = await computeDelegatorsForProvider(provider, linkedWallets);
|
|
514
|
+
for (const delegator of delegators) {
|
|
515
|
+
delegatorSet.add(delegator);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return delegatorSet;
|
|
519
|
+
}
|
|
520
|
+
async getLinkedWalletsWithDelegations(wallet, config) {
|
|
521
|
+
const linkedWallets = await this.getLinkedWallets(wallet);
|
|
522
|
+
const allWallets = new Set(linkedWallets);
|
|
523
|
+
const delegators = await this.getMainnetDelegationsForLinkedWallets(linkedWallets, config);
|
|
524
|
+
return [...new Set([...allWallets, ...delegators])];
|
|
525
|
+
}
|
|
526
|
+
async evaluateEntitledWallet(space, rootKey, allWallets, entitlements, xchainConfig) {
|
|
527
|
+
const { isExpired } = await space.getMembershipStatus(allWallets);
|
|
528
|
+
// otherwise you're trying to do something with an expired membership
|
|
529
|
+
if (isExpired) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
const isEveryOneSpace = entitlements.some((e) => e.userEntitlement?.includes(EVERYONE_ADDRESS));
|
|
533
|
+
if (isEveryOneSpace) {
|
|
534
|
+
return rootKey;
|
|
535
|
+
}
|
|
536
|
+
// Evaluate all user entitlements first, as they do not require external calls.
|
|
537
|
+
for (const entitlement of entitlements) {
|
|
538
|
+
for (const user of allWallets) {
|
|
539
|
+
if (entitlement.userEntitlement?.includes(user)) {
|
|
540
|
+
return user;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
// Accumulate all RuleDataV1 entitlements and convert to V2s.
|
|
545
|
+
const ruleEntitlements = entitlements
|
|
546
|
+
.filter((x) => x.entitlementType === EntitlementModuleType.RuleEntitlement &&
|
|
547
|
+
x.ruleEntitlement?.kind == 'v1')
|
|
548
|
+
.map((x) => convertRuleDataV1ToV2(x.ruleEntitlement.rules));
|
|
549
|
+
// Add all RuleDataV2 entitlements.
|
|
550
|
+
ruleEntitlements.push(...entitlements
|
|
551
|
+
.filter((x) => x.entitlementType === EntitlementModuleType.RuleEntitlementV2 &&
|
|
552
|
+
x.ruleEntitlement?.kind == 'v2')
|
|
553
|
+
.map((x) => x.ruleEntitlement.rules));
|
|
554
|
+
return await Promise.any(ruleEntitlements.map(async (ruleData) => {
|
|
555
|
+
if (!ruleData) {
|
|
556
|
+
throw new Error('Rule data not found');
|
|
557
|
+
}
|
|
558
|
+
const operations = ruleDataToOperations(ruleData);
|
|
559
|
+
const result = await evaluateOperationsForEntitledWallet(operations, allWallets, xchainConfig);
|
|
560
|
+
if (result !== ethers.constants.AddressZero) {
|
|
561
|
+
return result;
|
|
562
|
+
}
|
|
563
|
+
// This is not a true error, but is used here so that the Promise.any will not
|
|
564
|
+
// resolve with an unentitled wallet.
|
|
565
|
+
throw new NoEntitledWalletError();
|
|
566
|
+
})).catch(NoEntitledWalletError.throwIfRuntimeErrors);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Checks if user has a wallet entitled to join a space based on the minter role rule entitlements
|
|
570
|
+
*/
|
|
571
|
+
async getEntitledWalletForJoiningSpace(spaceId, rootKey, xchainConfig, skipCache = false) {
|
|
572
|
+
const key = Keyable.spaceEntitlementEvaluation(spaceId, rootKey, Permission.JoinSpace);
|
|
573
|
+
const { value } = await this.entitledWalletCache.executeUsingCache(key, async () => {
|
|
574
|
+
const entitledWallet = await this.getEntitledWalletForJoiningSpaceUncached(spaceId, rootKey, xchainConfig);
|
|
575
|
+
return new EntitledWalletCacheResult(entitledWallet);
|
|
576
|
+
}, { skipCache });
|
|
577
|
+
return value;
|
|
578
|
+
}
|
|
579
|
+
async getEntitledWalletForJoiningSpaceUncached(spaceId, rootKey, xchainConfig) {
|
|
580
|
+
const allWallets = await this.getLinkedWalletsWithDelegations(rootKey, xchainConfig);
|
|
581
|
+
const space = this.getSpace(spaceId);
|
|
582
|
+
if (!space) {
|
|
583
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
584
|
+
}
|
|
585
|
+
const owner = await space.Ownable.getOwner();
|
|
586
|
+
// Space owner is entitled to all channels
|
|
587
|
+
if (allWallets.includes(owner)) {
|
|
588
|
+
return owner;
|
|
589
|
+
}
|
|
590
|
+
const promises = allWallets.map(async (wallet) => this.walletAddressIsBanned(spaceId, wallet).then((r) => r === true ? true : Promise.reject(new Error('Wallet is not banned'))));
|
|
591
|
+
try {
|
|
592
|
+
// If any promise resolves (meaning a wallet IS banned), this succeeds.
|
|
593
|
+
await Promise.any(promises);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
catch (error) {
|
|
597
|
+
// all promises rejected, meaning no wallets are banned
|
|
598
|
+
}
|
|
599
|
+
const entitlements = await this.getEntitlementsForPermission(spaceId, Permission.JoinSpace);
|
|
600
|
+
return await this.evaluateEntitledWallet(space, rootKey, allWallets, entitlements, xchainConfig);
|
|
601
|
+
}
|
|
602
|
+
async isEntitledToSpace(spaceId, userId, permission, skipCache = false) {
|
|
603
|
+
const key = Keyable.spaceEntitlementEvaluation(spaceId, userId, permission);
|
|
604
|
+
const { value } = await this.entitlementEvaluationCache.executeUsingCache(key, async () => {
|
|
605
|
+
const isEntitled = await this.isEntitledToSpaceUncached(spaceId, userId, permission);
|
|
606
|
+
return new BooleanCacheResult(isEntitled);
|
|
607
|
+
}, { skipCache });
|
|
608
|
+
return value;
|
|
609
|
+
}
|
|
610
|
+
async isAppInstalled(spaceId, botAppAddress) {
|
|
611
|
+
const space = this.getSpace(spaceId);
|
|
612
|
+
if (!space) {
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
615
|
+
return space.AppAccount.read.isAppInstalled(botAppAddress);
|
|
616
|
+
}
|
|
617
|
+
async isAppEntitled(spaceId, botId, botAppAddress, permission) {
|
|
618
|
+
const space = this.getSpace(spaceId);
|
|
619
|
+
if (!space) {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
const permissionBytes = ethers.utils.formatBytes32String(permission);
|
|
623
|
+
return space.AppAccount.read.isAppEntitled(botAppAddress, botId, permissionBytes);
|
|
624
|
+
}
|
|
625
|
+
async isEntitledToSpaceUncached(spaceId, user, permission) {
|
|
626
|
+
const space = this.getSpace(spaceId);
|
|
627
|
+
if (!space) {
|
|
628
|
+
return false;
|
|
629
|
+
}
|
|
630
|
+
if (permission === Permission.JoinSpace) {
|
|
631
|
+
throw new Error('use getEntitledWalletForJoiningSpace instead of isEntitledToSpace');
|
|
632
|
+
}
|
|
633
|
+
return space.Entitlements.read.isEntitledToSpace(user, permission);
|
|
634
|
+
}
|
|
635
|
+
async isEntitledToChannel(spaceId, channelNetworkId, userId, permission, xchainConfig = EmptyXchainConfig, skipCache = false) {
|
|
636
|
+
const key = Keyable.channelEntitlementEvaluation(spaceId, channelNetworkId, userId, permission);
|
|
637
|
+
const { value } = await this.entitlementEvaluationCache.executeUsingCache(key, async () => {
|
|
638
|
+
const isEntitled = await this.isEntitledToChannelUncached(spaceId, channelNetworkId, userId, permission, xchainConfig);
|
|
639
|
+
return new BooleanCacheResult(isEntitled);
|
|
640
|
+
}, { skipCache });
|
|
641
|
+
return value;
|
|
642
|
+
}
|
|
643
|
+
async isEntitledToChannelUncached(spaceId, channelNetworkId, user, permission, xchainConfig) {
|
|
644
|
+
const space = this.getSpace(spaceId);
|
|
645
|
+
if (!space) {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
649
|
+
const linkedWallets = await this.getLinkedWalletsWithDelegations(user, xchainConfig);
|
|
650
|
+
const owner = await space.Ownable.getOwner();
|
|
651
|
+
// Space owner is entitled to all channels
|
|
652
|
+
if (linkedWallets.includes(owner)) {
|
|
653
|
+
return true;
|
|
654
|
+
}
|
|
655
|
+
const promises = linkedWallets.map(async (wallet) => this.walletAddressIsBanned(spaceId, wallet).then((r) => r === true ? true : Promise.reject(new Error('Wallet is not banned'))));
|
|
656
|
+
try {
|
|
657
|
+
// If any promise resolves (meaning a wallet IS banned), this succeeds.
|
|
658
|
+
await Promise.any(promises);
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
catch (error) {
|
|
662
|
+
// all promises rejected, meaning no wallets are banned
|
|
663
|
+
}
|
|
664
|
+
const entitlements = await this.getChannelEntitlementsForPermission(spaceId, channelId, permission);
|
|
665
|
+
const entitledWallet = await this.evaluateEntitledWallet(space, user, linkedWallets, entitlements, xchainConfig);
|
|
666
|
+
return entitledWallet !== undefined;
|
|
667
|
+
}
|
|
668
|
+
parseSpaceFactoryError(error) {
|
|
669
|
+
if (!this.spaceRegistrar.SpaceArchitect) {
|
|
670
|
+
throw new Error('SpaceArchitect is not deployed properly.');
|
|
671
|
+
}
|
|
672
|
+
const decodedErr = this.spaceRegistrar.SpaceArchitect.parseError(error);
|
|
673
|
+
logger.error(decodedErr);
|
|
674
|
+
return decodedErr;
|
|
675
|
+
}
|
|
676
|
+
parseSpaceOwnerError(error) {
|
|
677
|
+
if (!this.spaceOwner) {
|
|
678
|
+
throw new Error('SpaceOwner is not deployed properly.');
|
|
679
|
+
}
|
|
680
|
+
const decodedErr = this.spaceOwner.parseError(error);
|
|
681
|
+
logger.error(decodedErr);
|
|
682
|
+
return decodedErr;
|
|
683
|
+
}
|
|
684
|
+
parseSpaceError(spaceId, error) {
|
|
685
|
+
const space = this.getSpace(spaceId);
|
|
686
|
+
if (!space) {
|
|
687
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
688
|
+
}
|
|
689
|
+
const decodedErr = space.parseError(error);
|
|
690
|
+
logger.error(decodedErr);
|
|
691
|
+
return decodedErr;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Attempts to parse an error against all contracts
|
|
695
|
+
* If you're error is not showing any data with this call, make sure the contract is listed either in parseSpaceError or nonSpaceContracts
|
|
696
|
+
* @param args
|
|
697
|
+
* @returns
|
|
698
|
+
*/
|
|
699
|
+
parseAllContractErrors(args) {
|
|
700
|
+
let err;
|
|
701
|
+
if (args.spaceId) {
|
|
702
|
+
err = this.parseSpaceError(args.spaceId, args.error);
|
|
703
|
+
}
|
|
704
|
+
if (err && err?.name !== UNKNOWN_ERROR) {
|
|
705
|
+
return err;
|
|
706
|
+
}
|
|
707
|
+
err = this.spaceRegistrar.SpaceArchitect.parseError(args.error);
|
|
708
|
+
if (err?.name !== UNKNOWN_ERROR) {
|
|
709
|
+
return err;
|
|
710
|
+
}
|
|
711
|
+
const nonSpaceContracts = [this.airdrop.riverPoints, this.pricingModules, this.walletLink];
|
|
712
|
+
for (const contract of nonSpaceContracts) {
|
|
713
|
+
if (!contract) {
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
err = contract.parseError(args.error);
|
|
717
|
+
if (err?.name !== UNKNOWN_ERROR) {
|
|
718
|
+
return err;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return err;
|
|
722
|
+
}
|
|
723
|
+
async parseSpaceLogs(spaceId, logs) {
|
|
724
|
+
const space = this.getSpace(spaceId);
|
|
725
|
+
if (!space) {
|
|
726
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
727
|
+
}
|
|
728
|
+
return logs.map((spaceLog) => {
|
|
729
|
+
try {
|
|
730
|
+
return space.parseLog(spaceLog);
|
|
731
|
+
}
|
|
732
|
+
catch (err) {
|
|
733
|
+
logger.error(err);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
async updateChannel(params, signer, txnOpts) {
|
|
739
|
+
const space = this.getSpace(params.spaceId);
|
|
740
|
+
if (!space) {
|
|
741
|
+
throw new Error(`Space with spaceId "${params.spaceId}" is not found.`);
|
|
742
|
+
}
|
|
743
|
+
const encodedCallData = await this.encodedUpdateChannelData(space, params);
|
|
744
|
+
return wrapTransaction(() => space.Multicall.write(signer).multicall(encodedCallData), txnOpts);
|
|
745
|
+
}
|
|
746
|
+
async encodedUpdateChannelData(space, params) {
|
|
747
|
+
const channelId = ensureHexPrefix(params.channelId);
|
|
748
|
+
if (isUpdateChannelStatusParams(params)) {
|
|
749
|
+
// When enabling or disabling channels, passing names and roles is not required.
|
|
750
|
+
// To ensure the contract accepts this exception, the metadata argument should be left empty.
|
|
751
|
+
return [
|
|
752
|
+
space.Channels.interface.encodeFunctionData('updateChannel', [channelId, '', true]),
|
|
753
|
+
];
|
|
754
|
+
}
|
|
755
|
+
// data for the multicall
|
|
756
|
+
const encodedCallData = [];
|
|
757
|
+
// update the channel metadata
|
|
758
|
+
encodedCallData.push(space.Channels.interface.encodeFunctionData('updateChannel', [
|
|
759
|
+
channelId,
|
|
760
|
+
stringifyChannelMetadataJSON({
|
|
761
|
+
name: params.channelName,
|
|
762
|
+
description: params.channelDescription,
|
|
763
|
+
}),
|
|
764
|
+
params.disabled ?? false, // default to false
|
|
765
|
+
]));
|
|
766
|
+
// update any channel role changes
|
|
767
|
+
const encodedUpdateChannelRoles = await this.encodeUpdateChannelRoles(space, params.channelId, params.roleIds);
|
|
768
|
+
for (const callData of encodedUpdateChannelRoles) {
|
|
769
|
+
encodedCallData.push(callData);
|
|
770
|
+
}
|
|
771
|
+
return encodedCallData;
|
|
772
|
+
}
|
|
773
|
+
async removeChannel(params, signer, txnOpts) {
|
|
774
|
+
const space = this.getSpace(params.spaceId);
|
|
775
|
+
if (!space) {
|
|
776
|
+
throw new Error(`Space with spaceId "${params.spaceId}" is not found.`);
|
|
777
|
+
}
|
|
778
|
+
return wrapTransaction(() => space.Channels.write(signer).removeChannel(params.channelId), txnOpts);
|
|
779
|
+
}
|
|
780
|
+
async legacyUpdateRole(params, signer, txnOpts) {
|
|
781
|
+
const space = this.getSpace(params.spaceNetworkId);
|
|
782
|
+
if (!space) {
|
|
783
|
+
throw new Error(`Space with spaceId "${params.spaceNetworkId}" is not found.`);
|
|
784
|
+
}
|
|
785
|
+
const updatedEntitlemets = await this.createLegacyUpdatedEntitlements(space, params);
|
|
786
|
+
return wrapTransaction(() => space.Roles.write(signer).updateRole(params.roleId, params.roleName, params.permissions, updatedEntitlemets), txnOpts);
|
|
787
|
+
}
|
|
788
|
+
async updateRole(params, signer, txnOpts) {
|
|
789
|
+
const space = this.getSpace(params.spaceNetworkId);
|
|
790
|
+
if (!space) {
|
|
791
|
+
throw new Error(`Space with spaceId "${params.spaceNetworkId}" is not found.`);
|
|
792
|
+
}
|
|
793
|
+
const updatedEntitlemets = await this.createUpdatedEntitlements(space, params);
|
|
794
|
+
return wrapTransaction(() => space.Roles.write(signer).updateRole(params.roleId, params.roleName, params.permissions, updatedEntitlemets), txnOpts);
|
|
795
|
+
}
|
|
796
|
+
async getChannelPermissionOverrides(spaceId, roleId, channelNetworkId) {
|
|
797
|
+
const space = this.getSpace(spaceId);
|
|
798
|
+
if (!space) {
|
|
799
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
800
|
+
}
|
|
801
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
802
|
+
return (await space.Roles.read.getChannelPermissionOverrides(roleId, channelId)).filter(isPermission);
|
|
803
|
+
}
|
|
804
|
+
async setChannelPermissionOverrides(params, signer, txnOpts) {
|
|
805
|
+
const space = this.getSpace(params.spaceNetworkId);
|
|
806
|
+
if (!space) {
|
|
807
|
+
throw new Error(`Space with spaceId "${params.spaceNetworkId}" is not found.`);
|
|
808
|
+
}
|
|
809
|
+
const channelId = ensureHexPrefix(params.channelId);
|
|
810
|
+
return wrapTransaction(() => space.Roles.write(signer).setChannelPermissionOverrides(params.roleId, channelId, params.permissions), txnOpts);
|
|
811
|
+
}
|
|
812
|
+
async clearChannelPermissionOverrides(params, signer, txnOpts) {
|
|
813
|
+
const space = this.getSpace(params.spaceNetworkId);
|
|
814
|
+
if (!space) {
|
|
815
|
+
throw new Error(`Space with spaceId "${params.spaceNetworkId}" is not found.`);
|
|
816
|
+
}
|
|
817
|
+
const channelId = ensureHexPrefix(params.channelId);
|
|
818
|
+
return wrapTransaction(() => space.Roles.write(signer).clearChannelPermissionOverrides(params.roleId, channelId), txnOpts);
|
|
819
|
+
}
|
|
820
|
+
async setSpaceAccess(spaceId, disabled, signer, txnOpts) {
|
|
821
|
+
const space = this.getSpace(spaceId);
|
|
822
|
+
if (!space) {
|
|
823
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
824
|
+
}
|
|
825
|
+
if (disabled) {
|
|
826
|
+
return wrapTransaction(() => space.Pausable.write(signer).pause(), txnOpts);
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
return wrapTransaction(() => space.Pausable.write(signer).unpause(), txnOpts);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
*
|
|
834
|
+
* @param spaceId
|
|
835
|
+
* @param priceInWei
|
|
836
|
+
* @param signer
|
|
837
|
+
*/
|
|
838
|
+
async setMembershipPrice(spaceId, priceInWei, signer, txnOpts) {
|
|
839
|
+
const space = this.getSpace(spaceId);
|
|
840
|
+
if (!space) {
|
|
841
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
842
|
+
}
|
|
843
|
+
return wrapTransaction(() => space.Membership.write(signer).setMembershipPrice(priceInWei), txnOpts);
|
|
844
|
+
}
|
|
845
|
+
async setMembershipPricingModule(spaceId, pricingModule, signer, txnOpts) {
|
|
846
|
+
const space = this.getSpace(spaceId);
|
|
847
|
+
if (!space) {
|
|
848
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
849
|
+
}
|
|
850
|
+
return wrapTransaction(() => space.Membership.write(signer).setMembershipPricingModule(pricingModule), txnOpts);
|
|
851
|
+
}
|
|
852
|
+
async setMembershipLimit(spaceId, limit, signer, txnOpts) {
|
|
853
|
+
const space = this.getSpace(spaceId);
|
|
854
|
+
if (!space) {
|
|
855
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
856
|
+
}
|
|
857
|
+
return wrapTransaction(() => space.Membership.write(signer).setMembershipLimit(limit), txnOpts);
|
|
858
|
+
}
|
|
859
|
+
async setMembershipFreeAllocation(spaceId, freeAllocation, signer, txnOpts) {
|
|
860
|
+
const space = this.getSpace(spaceId);
|
|
861
|
+
if (!space) {
|
|
862
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
863
|
+
}
|
|
864
|
+
return wrapTransaction(() => space.Membership.write(signer).setMembershipFreeAllocation(freeAllocation), txnOpts);
|
|
865
|
+
}
|
|
866
|
+
async setChannelAccess(spaceId, channelNetworkId, disabled, signer, txnOpts) {
|
|
867
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
868
|
+
const space = this.getSpace(spaceId);
|
|
869
|
+
if (!space) {
|
|
870
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
871
|
+
}
|
|
872
|
+
return wrapTransaction(() => space.Channels.write(signer).updateChannel(channelId, '', disabled), txnOpts);
|
|
873
|
+
}
|
|
874
|
+
async getSpaceMembershipTokenAddress(spaceId) {
|
|
875
|
+
const space = this.getSpace(spaceId);
|
|
876
|
+
if (!space) {
|
|
877
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
878
|
+
}
|
|
879
|
+
return space.Membership.address;
|
|
880
|
+
}
|
|
881
|
+
async getJoinSpacePriceDetails(spaceId) {
|
|
882
|
+
const space = this.getSpace(spaceId);
|
|
883
|
+
if (!space) {
|
|
884
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
885
|
+
}
|
|
886
|
+
// membershipPrice is either the maximum of either the price set during space creation, or the PlatformRequirements membership fee
|
|
887
|
+
// it will always be a value regardless of whether the space has free allocations
|
|
888
|
+
const membershipPriceEncoded = space.Membership.interface.encodeFunctionData('getMembershipPrice');
|
|
889
|
+
// totalSupply = number of memberships minted
|
|
890
|
+
const totalSupplyEncoded = space.ERC721A.interface.encodeFunctionData('totalSupply');
|
|
891
|
+
// free allocation is set at space creation and is unchanging - it neither increases nor decreases
|
|
892
|
+
// if totalSupply < freeAllocation, the contracts won't charge for minting a membership nft,
|
|
893
|
+
// else it will charge the membershipPrice
|
|
894
|
+
const freeAllocationEncoded = space.Membership.interface.encodeFunctionData('getMembershipFreeAllocation');
|
|
895
|
+
const protocolFeeEncoded = space.Membership.interface.encodeFunctionData('getProtocolFee');
|
|
896
|
+
const [membershipPriceResult, totalSupplyResult, freeAllocationResult, protocolFeeResult] = await space.Multicall.read.callStatic.multicall([
|
|
897
|
+
membershipPriceEncoded,
|
|
898
|
+
totalSupplyEncoded,
|
|
899
|
+
freeAllocationEncoded,
|
|
900
|
+
protocolFeeEncoded,
|
|
901
|
+
]);
|
|
902
|
+
try {
|
|
903
|
+
const membershipPrice = space.Membership.interface.decodeFunctionResult('getMembershipPrice', membershipPriceResult)[0];
|
|
904
|
+
const totalSupply = space.ERC721A.interface.decodeFunctionResult('totalSupply', totalSupplyResult)[0];
|
|
905
|
+
const freeAllocation = space.Membership.interface.decodeFunctionResult('getMembershipFreeAllocation', freeAllocationResult)[0];
|
|
906
|
+
const protocolFee = space.Membership.interface.decodeFunctionResult('getProtocolFee', protocolFeeResult)[0];
|
|
907
|
+
// remainingFreeSupply = freeAllocation - totalSupply (if positive)
|
|
908
|
+
const remainingFreeSupply = totalSupply.lt(freeAllocation)
|
|
909
|
+
? freeAllocation.sub(totalSupply)
|
|
910
|
+
: ethers.BigNumber.from(0);
|
|
911
|
+
return {
|
|
912
|
+
price: remainingFreeSupply.gt(0) ? ethers.BigNumber.from(0) : membershipPrice,
|
|
913
|
+
remainingFreeSupply,
|
|
914
|
+
protocolFee,
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
catch (error) {
|
|
918
|
+
logger.error('getJoinSpacePriceDetails: Error decoding membership price', error);
|
|
919
|
+
throw error;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
async getMembershipFreeAllocation(spaceId) {
|
|
923
|
+
const space = this.getSpace(spaceId);
|
|
924
|
+
if (!space) {
|
|
925
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
926
|
+
}
|
|
927
|
+
return space.Membership.read.getMembershipFreeAllocation();
|
|
928
|
+
}
|
|
929
|
+
async joinSpace(spaceId, recipient, signer, txnOpts) {
|
|
930
|
+
const joinSpaceStart = Date.now();
|
|
931
|
+
logger.log('joinSpace result before wrap', spaceId);
|
|
932
|
+
const getSpaceStart = Date.now();
|
|
933
|
+
const space = this.getSpace(spaceId);
|
|
934
|
+
if (!space) {
|
|
935
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
936
|
+
}
|
|
937
|
+
const [spaceCurrency, { price }] = await Promise.all([
|
|
938
|
+
space.Membership.read.getMembershipCurrency(),
|
|
939
|
+
this.getJoinSpacePriceDetails(spaceId),
|
|
940
|
+
]);
|
|
941
|
+
const blockNumber = await space.provider?.getBlockNumber();
|
|
942
|
+
const startIssuedListener = space.Membership.listenForMembershipToken({
|
|
943
|
+
receiver: recipient,
|
|
944
|
+
startingBlock: blockNumber,
|
|
945
|
+
});
|
|
946
|
+
logger.log('joinSpace before blockNumber', Date.now() - getSpaceStart, blockNumber);
|
|
947
|
+
const getPriceStart = Date.now();
|
|
948
|
+
logger.log('joinSpace getMembershipPrice', Date.now() - getPriceStart);
|
|
949
|
+
const wrapStart = Date.now();
|
|
950
|
+
const issuedListener = startIssuedListener();
|
|
951
|
+
const result = await wrapTransaction(async () => {
|
|
952
|
+
// Set gas limit instead of using estimateGas
|
|
953
|
+
// As the estimateGas is not reliable for this contract
|
|
954
|
+
return await space.Membership.write(signer)['joinSpace(address)'](recipient, {
|
|
955
|
+
gasLimit: 1_500_000,
|
|
956
|
+
value: spaceCurrency.toLowerCase() === ETH_ADDRESS.toLowerCase() ? price : 0,
|
|
957
|
+
});
|
|
958
|
+
}, txnOpts);
|
|
959
|
+
const blockNumberAfterTx = await space.provider?.getBlockNumber();
|
|
960
|
+
logger.log('joinSpace wrap', Date.now() - wrapStart, blockNumberAfterTx);
|
|
961
|
+
const issued = await issuedListener;
|
|
962
|
+
const blockNumberAfter = await space.provider?.getBlockNumber();
|
|
963
|
+
logger.log('joinSpace after blockNumber', Date.now() - joinSpaceStart, blockNumberAfter, result, issued);
|
|
964
|
+
return issued;
|
|
965
|
+
}
|
|
966
|
+
async hasSpaceMembership(spaceId, addresses) {
|
|
967
|
+
const membershipStatus = await this.getMembershipStatus(spaceId, addresses);
|
|
968
|
+
return membershipStatus.isMember && !membershipStatus.isExpired;
|
|
969
|
+
}
|
|
970
|
+
async getMembershipStatus(spaceId, addresses) {
|
|
971
|
+
const space = this.getSpace(spaceId);
|
|
972
|
+
if (!space) {
|
|
973
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
974
|
+
}
|
|
975
|
+
return space.getMembershipStatus(addresses);
|
|
976
|
+
}
|
|
977
|
+
async getMembershipSupply(spaceId) {
|
|
978
|
+
const space = this.getSpace(spaceId);
|
|
979
|
+
if (!space) {
|
|
980
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
981
|
+
}
|
|
982
|
+
const totalSupply = await space.ERC721A.read.totalSupply();
|
|
983
|
+
return { totalSupply: totalSupply.toNumber() };
|
|
984
|
+
}
|
|
985
|
+
async getMembershipInfo(spaceId) {
|
|
986
|
+
const space = this.getSpace(spaceId);
|
|
987
|
+
if (!space) {
|
|
988
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
989
|
+
}
|
|
990
|
+
const [joinSpacePriceDetails, limit, currency, feeRecipient, duration, totalSupply, pricingModule,] = await Promise.all([
|
|
991
|
+
this.getJoinSpacePriceDetails(spaceId),
|
|
992
|
+
space.Membership.read.getMembershipLimit(),
|
|
993
|
+
space.Membership.read.getMembershipCurrency(),
|
|
994
|
+
space.Ownable.getOwner(),
|
|
995
|
+
space.Membership.read.getMembershipDuration(),
|
|
996
|
+
space.ERC721A.read.totalSupply(),
|
|
997
|
+
space.Membership.read.getMembershipPricingModule(),
|
|
998
|
+
]);
|
|
999
|
+
const { price, remainingFreeSupply } = joinSpacePriceDetails;
|
|
1000
|
+
return {
|
|
1001
|
+
price, // keep as BigNumber (wei)
|
|
1002
|
+
maxSupply: limit.toNumber(),
|
|
1003
|
+
currency: currency,
|
|
1004
|
+
feeRecipient: feeRecipient,
|
|
1005
|
+
duration: duration.toNumber(),
|
|
1006
|
+
totalSupply: totalSupply.toNumber(),
|
|
1007
|
+
pricingModule: pricingModule,
|
|
1008
|
+
remainingFreeSupply: remainingFreeSupply.toNumber(),
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
getWalletLink() {
|
|
1012
|
+
return this.walletLink;
|
|
1013
|
+
}
|
|
1014
|
+
getSpace(spaceId) {
|
|
1015
|
+
return this.spaceRegistrar.getSpace(spaceId);
|
|
1016
|
+
}
|
|
1017
|
+
listPricingModules() {
|
|
1018
|
+
return this.pricingModules.listPricingModules();
|
|
1019
|
+
}
|
|
1020
|
+
async encodeUpdateChannelRoles(space, channelNetworkId, _updatedRoleIds) {
|
|
1021
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
1022
|
+
const encodedCallData = [];
|
|
1023
|
+
const [channelInfo] = await Promise.all([
|
|
1024
|
+
space.Channels.read.getChannel(channelId),
|
|
1025
|
+
space.getEntitlementShims(),
|
|
1026
|
+
]);
|
|
1027
|
+
const currentRoleIds = new Set(channelInfo.roleIds.map((r) => r.toNumber()));
|
|
1028
|
+
const updatedRoleIds = new Set(_updatedRoleIds);
|
|
1029
|
+
const rolesToRemove = [];
|
|
1030
|
+
const rolesToAdd = [];
|
|
1031
|
+
for (const r of updatedRoleIds) {
|
|
1032
|
+
// if the current role IDs does not have the updated role ID, then that role should be added.
|
|
1033
|
+
if (!currentRoleIds.has(r)) {
|
|
1034
|
+
rolesToAdd.push(r);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
for (const r of currentRoleIds) {
|
|
1038
|
+
// if the updated role IDs no longer have the current role ID, then that role should be removed.
|
|
1039
|
+
if (!updatedRoleIds.has(r)) {
|
|
1040
|
+
rolesToRemove.push(r);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
// encode the call data for each role to remove
|
|
1044
|
+
const encodedRemoveRoles = this.encodeRemoveRolesFromChannel(space, channelId, rolesToRemove);
|
|
1045
|
+
for (const callData of encodedRemoveRoles) {
|
|
1046
|
+
encodedCallData.push(callData);
|
|
1047
|
+
}
|
|
1048
|
+
// encode the call data for each role to add
|
|
1049
|
+
const encodedAddRoles = this.encodeAddRolesToChannel(space, channelId, rolesToAdd);
|
|
1050
|
+
for (const callData of encodedAddRoles) {
|
|
1051
|
+
encodedCallData.push(callData);
|
|
1052
|
+
}
|
|
1053
|
+
return encodedCallData;
|
|
1054
|
+
}
|
|
1055
|
+
encodeAddRolesToChannel(space, channelNetworkId, roleIds) {
|
|
1056
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
1057
|
+
const encodedCallData = [];
|
|
1058
|
+
for (const roleId of roleIds) {
|
|
1059
|
+
const encodedBytes = space.Channels.interface.encodeFunctionData('addRoleToChannel', [
|
|
1060
|
+
channelId,
|
|
1061
|
+
roleId,
|
|
1062
|
+
]);
|
|
1063
|
+
encodedCallData.push(encodedBytes);
|
|
1064
|
+
}
|
|
1065
|
+
return encodedCallData;
|
|
1066
|
+
}
|
|
1067
|
+
encodeRemoveRolesFromChannel(space, channelNetworkId, roleIds) {
|
|
1068
|
+
const channelId = ensureHexPrefix(channelNetworkId);
|
|
1069
|
+
const encodedCallData = [];
|
|
1070
|
+
for (const roleId of roleIds) {
|
|
1071
|
+
const encodedBytes = space.Channels.interface.encodeFunctionData('removeRoleFromChannel', [channelId, roleId]);
|
|
1072
|
+
encodedCallData.push(encodedBytes);
|
|
1073
|
+
}
|
|
1074
|
+
return encodedCallData;
|
|
1075
|
+
}
|
|
1076
|
+
async createLegacyUpdatedEntitlements(space, params) {
|
|
1077
|
+
return createLegacyEntitlementStruct(space, params.users, params.ruleData);
|
|
1078
|
+
}
|
|
1079
|
+
async createUpdatedEntitlements(space, params) {
|
|
1080
|
+
return createEntitlementStruct(space, params.users, params.ruleData);
|
|
1081
|
+
}
|
|
1082
|
+
async refreshMetadata(spaceId, signer, txnOpts) {
|
|
1083
|
+
const space = this.getSpace(spaceId);
|
|
1084
|
+
if (!space) {
|
|
1085
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
1086
|
+
}
|
|
1087
|
+
return wrapTransaction(() => space.Membership.metadata.write(signer).refreshMetadata(), txnOpts);
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Get the space address from the receipt and sender address
|
|
1091
|
+
* @param receipt - The receipt from the transaction
|
|
1092
|
+
* @param senderAddress - The address of the sender. Required for the case of a receipt containing multiple events of the same type.
|
|
1093
|
+
* @returns The space address or undefined if the receipt is not successful
|
|
1094
|
+
*/
|
|
1095
|
+
getSpaceAddress(receipt, senderAddress) {
|
|
1096
|
+
if (receipt.status !== 1) {
|
|
1097
|
+
return undefined;
|
|
1098
|
+
}
|
|
1099
|
+
for (const receiptLog of receipt.logs) {
|
|
1100
|
+
const spaceAddress = this.spaceRegistrar.SpaceArchitect.getSpaceAddressFromLog(receiptLog, senderAddress);
|
|
1101
|
+
if (spaceAddress) {
|
|
1102
|
+
return spaceAddress;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
return undefined;
|
|
1106
|
+
}
|
|
1107
|
+
getTipEvent(spaceId, receipt, senderAddress) {
|
|
1108
|
+
const space = this.getSpace(spaceId);
|
|
1109
|
+
if (!space) {
|
|
1110
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
1111
|
+
}
|
|
1112
|
+
return space.Tipping.getTipEvent(receipt, senderAddress);
|
|
1113
|
+
}
|
|
1114
|
+
withdrawSpaceFunds(spaceId, recipient, signer) {
|
|
1115
|
+
const space = this.getSpace(spaceId);
|
|
1116
|
+
if (!space) {
|
|
1117
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
1118
|
+
}
|
|
1119
|
+
return space.Treasury.write(signer).withdraw(ETH_ADDRESS, recipient);
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Get the token id for the owner
|
|
1123
|
+
* Returns the first token id matched from the linked wallets of the owner
|
|
1124
|
+
* @param spaceId - The space id
|
|
1125
|
+
* @param owner - The owner
|
|
1126
|
+
* @returns The token id
|
|
1127
|
+
*/
|
|
1128
|
+
async getTokenIdOfOwner(spaceId, owner, config = EmptyXchainConfig) {
|
|
1129
|
+
const space = this.getSpace(spaceId);
|
|
1130
|
+
if (!space) {
|
|
1131
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
1132
|
+
}
|
|
1133
|
+
const linkedWallets = await this.getLinkedWalletsWithDelegations(owner, config);
|
|
1134
|
+
const tokenIds = await space.getTokenIdsOfOwner(linkedWallets);
|
|
1135
|
+
return tokenIds[0];
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Send a tip using the new sendTip interface
|
|
1139
|
+
* @param args.tipParams - The tip parameters (SendTipParams)
|
|
1140
|
+
* @param args.signer - The signer to use for the tip
|
|
1141
|
+
* @param args.txnOpts - Optional transaction options
|
|
1142
|
+
* @param args.overrideExecution - Optional execution override
|
|
1143
|
+
* @returns The transaction
|
|
1144
|
+
*/
|
|
1145
|
+
async sendTip(args) {
|
|
1146
|
+
const { tipParams, signer, txnOpts, overrideExecution } = args;
|
|
1147
|
+
let recipientType;
|
|
1148
|
+
let encodedData;
|
|
1149
|
+
let tippingContract;
|
|
1150
|
+
switch (tipParams.type) {
|
|
1151
|
+
case 'member': {
|
|
1152
|
+
// TipRecipientType.Member = 0
|
|
1153
|
+
recipientType = 0;
|
|
1154
|
+
const { spaceId, receiver, tokenId, currency, amount, messageId, channelId } = tipParams;
|
|
1155
|
+
const space = this.getSpace(spaceId);
|
|
1156
|
+
if (!space) {
|
|
1157
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
1158
|
+
}
|
|
1159
|
+
tippingContract = space.Tipping;
|
|
1160
|
+
const metadataData = ethers.utils.defaultAbiCoder.encode(['bytes32', 'bytes32', 'uint256'], [ensureHexPrefix(messageId), ensureHexPrefix(channelId), tokenId]);
|
|
1161
|
+
// Encode struct MembershipTipParams
|
|
1162
|
+
encodedData = ethers.utils.defaultAbiCoder.encode([
|
|
1163
|
+
'tuple(address receiver, uint256 tokenId, address currency, uint256 amount, tuple(bytes32 messageId, bytes32 channelId, bytes data) metadata)',
|
|
1164
|
+
], [
|
|
1165
|
+
[
|
|
1166
|
+
receiver,
|
|
1167
|
+
tokenId,
|
|
1168
|
+
currency,
|
|
1169
|
+
amount,
|
|
1170
|
+
[ensureHexPrefix(messageId), ensureHexPrefix(channelId), metadataData],
|
|
1171
|
+
],
|
|
1172
|
+
]);
|
|
1173
|
+
break;
|
|
1174
|
+
}
|
|
1175
|
+
case 'bot': {
|
|
1176
|
+
// TipRecipientType.Bot = 1
|
|
1177
|
+
recipientType = 1;
|
|
1178
|
+
const { spaceId, receiver, appId, currency, amount, messageId, channelId } = tipParams;
|
|
1179
|
+
if (spaceId) {
|
|
1180
|
+
const space = this.getSpace(spaceId);
|
|
1181
|
+
if (!space) {
|
|
1182
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
1183
|
+
}
|
|
1184
|
+
tippingContract = space.Tipping;
|
|
1185
|
+
}
|
|
1186
|
+
else {
|
|
1187
|
+
if (!this.config.addresses.accountModules) {
|
|
1188
|
+
throw new Error('AccountModules address is not configured');
|
|
1189
|
+
}
|
|
1190
|
+
tippingContract = new ITippingShim(this.config.addresses.accountModules, this.provider);
|
|
1191
|
+
}
|
|
1192
|
+
const metadataData = ethers.utils.defaultAbiCoder.encode(['bytes32', 'bytes32'], [ensureHexPrefix(messageId), ensureHexPrefix(channelId)]);
|
|
1193
|
+
// Encode struct BotTipParams
|
|
1194
|
+
encodedData = ethers.utils.defaultAbiCoder.encode([
|
|
1195
|
+
'tuple(address receiver, address currency, bytes32 appId, uint256 amount, tuple(bytes32 messageId, bytes32 channelId, bytes data) metadata)',
|
|
1196
|
+
], [
|
|
1197
|
+
[
|
|
1198
|
+
receiver,
|
|
1199
|
+
currency,
|
|
1200
|
+
ensureHexPrefix(appId),
|
|
1201
|
+
amount,
|
|
1202
|
+
[ensureHexPrefix(messageId), ensureHexPrefix(channelId), metadataData],
|
|
1203
|
+
],
|
|
1204
|
+
]);
|
|
1205
|
+
break;
|
|
1206
|
+
}
|
|
1207
|
+
// DM tips (type: 'any') - calls the AccountModules contract directly
|
|
1208
|
+
case 'any': {
|
|
1209
|
+
// TipRecipientType.Any = 2
|
|
1210
|
+
recipientType = 2;
|
|
1211
|
+
const { receiver, currency, amount, messageId, channelId, sender: senderOverride, } = tipParams;
|
|
1212
|
+
const sender = senderOverride ?? (await signer.getAddress());
|
|
1213
|
+
if (!this.config.addresses.accountModules) {
|
|
1214
|
+
throw new Error('AccountModules address is not configured');
|
|
1215
|
+
}
|
|
1216
|
+
tippingContract = new ITippingShim(this.config.addresses.accountModules, this.provider);
|
|
1217
|
+
// Encode messageId and channelId into bytes data
|
|
1218
|
+
const data = ethers.utils.defaultAbiCoder.encode(['bytes32', 'bytes32'], [ensureHexPrefix(messageId), ensureHexPrefix(channelId)]);
|
|
1219
|
+
// Encode struct AnyTipParams
|
|
1220
|
+
encodedData = ethers.utils.defaultAbiCoder.encode([
|
|
1221
|
+
'tuple(address currency, address sender, address receiver, uint256 amount, bytes data)',
|
|
1222
|
+
], [[currency, sender, receiver, amount, data]]);
|
|
1223
|
+
break;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
return tippingContract.executeCall({
|
|
1227
|
+
signer,
|
|
1228
|
+
functionName: 'sendTip',
|
|
1229
|
+
args: [recipientType, encodedData],
|
|
1230
|
+
value: tipParams.currency.toLowerCase() === ETH_ADDRESS.toLowerCase()
|
|
1231
|
+
? tipParams.amount
|
|
1232
|
+
: undefined,
|
|
1233
|
+
overrideExecution,
|
|
1234
|
+
transactionOpts: txnOpts,
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Delegate staking within a space to an operator
|
|
1239
|
+
* @param args
|
|
1240
|
+
* @param args.spaceId - The space id
|
|
1241
|
+
* @param args.operatorAddress - The operator address
|
|
1242
|
+
* @returns The transaction
|
|
1243
|
+
*/
|
|
1244
|
+
async addSpaceDelegation(args) {
|
|
1245
|
+
const { spaceId, operatorAddress, signer, transactionOpts, overrideExecution } = args;
|
|
1246
|
+
const space = this.getSpace(spaceId);
|
|
1247
|
+
if (!space) {
|
|
1248
|
+
throw new Error(`Space with spaceId "${spaceId}" is not found.`);
|
|
1249
|
+
}
|
|
1250
|
+
const spaceAddress = space.Address;
|
|
1251
|
+
return this.baseRegistry.spaceDelegation.executeCall({
|
|
1252
|
+
signer,
|
|
1253
|
+
functionName: 'addSpaceDelegation',
|
|
1254
|
+
args: [spaceAddress, operatorAddress],
|
|
1255
|
+
overrideExecution,
|
|
1256
|
+
transactionOpts,
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
//# sourceMappingURL=SpaceDapp.js.map
|