@sudobility/contracts 0.14.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/README.md +353 -0
- package/artifacts/contracts/Mailer.sol/Mailer.d.ts +1146 -0
- package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +4 -0
- package/artifacts/contracts/Mailer.sol/Mailer.json +1096 -0
- package/artifacts/contracts/Mailer.sol/artifacts.d.ts +21 -0
- package/artifacts/contracts/MockUSDC.sol/MockUSDC.d.ts +284 -0
- package/artifacts/contracts/MockUSDC.sol/MockUSDC.dbg.json +4 -0
- package/artifacts/contracts/MockUSDC.sol/MockUSDC.json +234 -0
- package/artifacts/contracts/MockUSDC.sol/artifacts.d.ts +21 -0
- package/artifacts/contracts/interfaces/IERC20.sol/IERC20.d.ts +157 -0
- package/artifacts/contracts/interfaces/IERC20.sol/IERC20.dbg.json +4 -0
- package/artifacts/contracts/interfaces/IERC20.sol/IERC20.json +107 -0
- package/artifacts/contracts/interfaces/IERC20.sol/artifacts.d.ts +21 -0
- package/dist/evm/src/evm/index.d.ts +4 -0
- package/dist/evm/src/evm/index.d.ts.map +1 -0
- package/dist/evm/src/evm/index.js +10 -0
- package/dist/evm/src/evm/index.js.map +1 -0
- package/dist/evm/src/evm/mailer-client.d.ts +966 -0
- package/dist/evm/src/evm/mailer-client.d.ts.map +1 -0
- package/dist/evm/src/evm/mailer-client.js +619 -0
- package/dist/evm/src/evm/mailer-client.js.map +1 -0
- package/dist/evm/typechain-types/Mailer.d.ts +698 -0
- package/dist/evm/typechain-types/Mailer.d.ts.map +1 -0
- package/dist/evm/typechain-types/Mailer.js +3 -0
- package/dist/evm/typechain-types/Mailer.js.map +1 -0
- package/dist/evm/typechain-types/MockUSDC.d.ts +118 -0
- package/dist/evm/typechain-types/MockUSDC.d.ts.map +1 -0
- package/dist/evm/typechain-types/MockUSDC.js +3 -0
- package/dist/evm/typechain-types/MockUSDC.js.map +1 -0
- package/dist/evm/typechain-types/common.d.ts +51 -0
- package/dist/evm/typechain-types/common.d.ts.map +1 -0
- package/dist/evm/typechain-types/common.js +3 -0
- package/dist/evm/typechain-types/common.js.map +1 -0
- package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +875 -0
- package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -0
- package/dist/evm/typechain-types/factories/Mailer__factory.js +1125 -0
- package/dist/evm/typechain-types/factories/Mailer__factory.js.map +1 -0
- package/dist/evm/typechain-types/factories/MockUSDC__factory.d.ts +193 -0
- package/dist/evm/typechain-types/factories/MockUSDC__factory.d.ts.map +1 -0
- package/dist/evm/typechain-types/factories/MockUSDC__factory.js +263 -0
- package/dist/evm/typechain-types/factories/MockUSDC__factory.js.map +1 -0
- package/dist/evm/typechain-types/factories/index.d.ts +4 -0
- package/dist/evm/typechain-types/factories/index.d.ts.map +1 -0
- package/dist/evm/typechain-types/factories/index.js +45 -0
- package/dist/evm/typechain-types/factories/index.js.map +1 -0
- package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.d.ts +80 -0
- package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.d.ts.map +1 -0
- package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.js +116 -0
- package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.js.map +1 -0
- package/dist/evm/typechain-types/factories/interfaces/index.d.ts +2 -0
- package/dist/evm/typechain-types/factories/interfaces/index.d.ts.map +1 -0
- package/dist/evm/typechain-types/factories/interfaces/index.js +9 -0
- package/dist/evm/typechain-types/factories/interfaces/index.js.map +1 -0
- package/dist/evm/typechain-types/index.d.ts +10 -0
- package/dist/evm/typechain-types/index.d.ts.map +1 -0
- package/dist/evm/typechain-types/index.js +44 -0
- package/dist/evm/typechain-types/index.js.map +1 -0
- package/dist/evm/typechain-types/interfaces/IERC20.d.ts +70 -0
- package/dist/evm/typechain-types/interfaces/IERC20.d.ts.map +1 -0
- package/dist/evm/typechain-types/interfaces/IERC20.js +3 -0
- package/dist/evm/typechain-types/interfaces/IERC20.js.map +1 -0
- package/dist/evm/typechain-types/interfaces/index.d.ts +2 -0
- package/dist/evm/typechain-types/interfaces/index.d.ts.map +1 -0
- package/dist/evm/typechain-types/interfaces/index.js +3 -0
- package/dist/evm/typechain-types/interfaces/index.js.map +1 -0
- package/dist/solana/solana/index.d.ts +3 -0
- package/dist/solana/solana/index.d.ts.map +1 -0
- package/dist/solana/solana/index.js +21 -0
- package/dist/solana/solana/index.js.map +1 -0
- package/dist/solana/solana/mailer-client.d.ts +282 -0
- package/dist/solana/solana/mailer-client.d.ts.map +1 -0
- package/dist/solana/solana/mailer-client.js +989 -0
- package/dist/solana/solana/mailer-client.js.map +1 -0
- package/dist/solana/solana/types.d.ts +28 -0
- package/dist/solana/solana/types.d.ts.map +1 -0
- package/dist/solana/solana/types.js +23 -0
- package/dist/solana/solana/types.js.map +1 -0
- package/dist/solana/utils/currency.d.ts +26 -0
- package/dist/solana/utils/currency.d.ts.map +1 -0
- package/dist/solana/utils/currency.js +36 -0
- package/dist/solana/utils/currency.js.map +1 -0
- package/dist/unified/package.json +3 -0
- package/dist/unified/src/evm/index.d.ts +4 -0
- package/dist/unified/src/evm/index.d.ts.map +1 -0
- package/dist/unified/src/evm/index.js +10 -0
- package/dist/unified/src/evm/index.js.map +1 -0
- package/dist/unified/src/evm/mailer-client.d.ts +966 -0
- package/dist/unified/src/evm/mailer-client.d.ts.map +1 -0
- package/dist/unified/src/evm/mailer-client.js +619 -0
- package/dist/unified/src/evm/mailer-client.js.map +1 -0
- package/dist/unified/src/react/context/MailerProvider.d.ts +102 -0
- package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -0
- package/dist/unified/src/react/context/MailerProvider.js +160 -0
- package/dist/unified/src/react/context/MailerProvider.js.map +1 -0
- package/dist/unified/src/react/hooks/useMailerMutations.d.ts +301 -0
- package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -0
- package/dist/unified/src/react/hooks/useMailerMutations.js +417 -0
- package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -0
- package/dist/unified/src/react/hooks/useMailerQueries.d.ts +130 -0
- package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -0
- package/dist/unified/src/react/hooks/useMailerQueries.js +197 -0
- package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -0
- package/dist/unified/src/react/index.d.ts +37 -0
- package/dist/unified/src/react/index.d.ts.map +1 -0
- package/dist/unified/src/react/index.js +70 -0
- package/dist/unified/src/react/index.js.map +1 -0
- package/dist/unified/src/solana/index.d.ts +3 -0
- package/dist/unified/src/solana/index.d.ts.map +1 -0
- package/dist/unified/src/solana/index.js +21 -0
- package/dist/unified/src/solana/index.js.map +1 -0
- package/dist/unified/src/solana/mailer-client.d.ts +282 -0
- package/dist/unified/src/solana/mailer-client.d.ts.map +1 -0
- package/dist/unified/src/solana/mailer-client.js +989 -0
- package/dist/unified/src/solana/mailer-client.js.map +1 -0
- package/dist/unified/src/solana/types.d.ts +28 -0
- package/dist/unified/src/solana/types.d.ts.map +1 -0
- package/dist/unified/src/solana/types.js +23 -0
- package/dist/unified/src/solana/types.js.map +1 -0
- package/dist/unified/src/unified/index.d.ts +4 -0
- package/dist/unified/src/unified/index.d.ts.map +1 -0
- package/dist/unified/src/unified/index.js +9 -0
- package/dist/unified/src/unified/index.js.map +1 -0
- package/dist/unified/src/unified/onchain-mailer-client.d.ts +173 -0
- package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -0
- package/dist/unified/src/unified/onchain-mailer-client.js +1048 -0
- package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -0
- package/dist/unified/src/unified/types.d.ts +47 -0
- package/dist/unified/src/unified/types.d.ts.map +1 -0
- package/dist/unified/src/unified/types.js +3 -0
- package/dist/unified/src/unified/types.js.map +1 -0
- package/dist/unified/src/unified/wallet-detector.d.ts +28 -0
- package/dist/unified/src/unified/wallet-detector.d.ts.map +1 -0
- package/dist/unified/src/unified/wallet-detector.js +63 -0
- package/dist/unified/src/unified/wallet-detector.js.map +1 -0
- package/dist/unified/src/utils/chain-config.d.ts +75 -0
- package/dist/unified/src/utils/chain-config.d.ts.map +1 -0
- package/dist/unified/src/utils/chain-config.js +203 -0
- package/dist/unified/src/utils/chain-config.js.map +1 -0
- package/dist/unified/src/utils/currency.d.ts +26 -0
- package/dist/unified/src/utils/currency.d.ts.map +1 -0
- package/dist/unified/src/utils/currency.js +36 -0
- package/dist/unified/src/utils/currency.js.map +1 -0
- package/dist/unified/src/utils/index.d.ts +4 -0
- package/dist/unified/src/utils/index.d.ts.map +1 -0
- package/dist/unified/src/utils/index.js +20 -0
- package/dist/unified/src/utils/index.js.map +1 -0
- package/dist/unified/src/utils/validation.d.ts +10 -0
- package/dist/unified/src/utils/validation.d.ts.map +1 -0
- package/dist/unified/src/utils/validation.js +102 -0
- package/dist/unified/src/utils/validation.js.map +1 -0
- package/dist/unified/typechain-types/Mailer.d.ts +698 -0
- package/dist/unified/typechain-types/Mailer.d.ts.map +1 -0
- package/dist/unified/typechain-types/Mailer.js +3 -0
- package/dist/unified/typechain-types/Mailer.js.map +1 -0
- package/dist/unified/typechain-types/MockUSDC.d.ts +118 -0
- package/dist/unified/typechain-types/MockUSDC.d.ts.map +1 -0
- package/dist/unified/typechain-types/MockUSDC.js +3 -0
- package/dist/unified/typechain-types/MockUSDC.js.map +1 -0
- package/dist/unified/typechain-types/common.d.ts +51 -0
- package/dist/unified/typechain-types/common.d.ts.map +1 -0
- package/dist/unified/typechain-types/common.js +3 -0
- package/dist/unified/typechain-types/common.js.map +1 -0
- package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +875 -0
- package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -0
- package/dist/unified/typechain-types/factories/Mailer__factory.js +1125 -0
- package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -0
- package/dist/unified/typechain-types/factories/MockUSDC__factory.d.ts +193 -0
- package/dist/unified/typechain-types/factories/MockUSDC__factory.d.ts.map +1 -0
- package/dist/unified/typechain-types/factories/MockUSDC__factory.js +263 -0
- package/dist/unified/typechain-types/factories/MockUSDC__factory.js.map +1 -0
- package/dist/unified/typechain-types/factories/index.d.ts +4 -0
- package/dist/unified/typechain-types/factories/index.d.ts.map +1 -0
- package/dist/unified/typechain-types/factories/index.js +45 -0
- package/dist/unified/typechain-types/factories/index.js.map +1 -0
- package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.d.ts +80 -0
- package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.d.ts.map +1 -0
- package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.js +116 -0
- package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.js.map +1 -0
- package/dist/unified/typechain-types/factories/interfaces/index.d.ts +2 -0
- package/dist/unified/typechain-types/factories/interfaces/index.d.ts.map +1 -0
- package/dist/unified/typechain-types/factories/interfaces/index.js +9 -0
- package/dist/unified/typechain-types/factories/interfaces/index.js.map +1 -0
- package/dist/unified/typechain-types/index.d.ts +10 -0
- package/dist/unified/typechain-types/index.d.ts.map +1 -0
- package/dist/unified/typechain-types/index.js +44 -0
- package/dist/unified/typechain-types/index.js.map +1 -0
- package/dist/unified/typechain-types/interfaces/IERC20.d.ts +70 -0
- package/dist/unified/typechain-types/interfaces/IERC20.d.ts.map +1 -0
- package/dist/unified/typechain-types/interfaces/IERC20.js +3 -0
- package/dist/unified/typechain-types/interfaces/IERC20.js.map +1 -0
- package/dist/unified/typechain-types/interfaces/index.d.ts +2 -0
- package/dist/unified/typechain-types/interfaces/index.d.ts.map +1 -0
- package/dist/unified/typechain-types/interfaces/index.js +3 -0
- package/dist/unified/typechain-types/interfaces/index.js.map +1 -0
- package/dist/unified-esm/src/evm/index.d.ts +4 -0
- package/dist/unified-esm/src/evm/index.d.ts.map +1 -0
- package/dist/unified-esm/src/evm/index.js +5 -0
- package/dist/unified-esm/src/evm/index.js.map +1 -0
- package/dist/unified-esm/src/evm/mailer-client.d.ts +966 -0
- package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -0
- package/dist/unified-esm/src/evm/mailer-client.js +615 -0
- package/dist/unified-esm/src/evm/mailer-client.js.map +1 -0
- package/dist/unified-esm/src/react/context/MailerProvider.d.ts +102 -0
- package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -0
- package/dist/unified-esm/src/react/context/MailerProvider.js +120 -0
- package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -0
- package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +301 -0
- package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -0
- package/dist/unified-esm/src/react/hooks/useMailerMutations.js +400 -0
- package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -0
- package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +130 -0
- package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -0
- package/dist/unified-esm/src/react/hooks/useMailerQueries.js +186 -0
- package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -0
- package/dist/unified-esm/src/react/index.d.ts +37 -0
- package/dist/unified-esm/src/react/index.d.ts.map +1 -0
- package/dist/unified-esm/src/react/index.js +39 -0
- package/dist/unified-esm/src/react/index.js.map +1 -0
- package/dist/unified-esm/src/solana/index.d.ts +3 -0
- package/dist/unified-esm/src/solana/index.d.ts.map +1 -0
- package/dist/unified-esm/src/solana/index.js +3 -0
- package/dist/unified-esm/src/solana/index.js.map +1 -0
- package/dist/unified-esm/src/solana/mailer-client.d.ts +282 -0
- package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -0
- package/dist/unified-esm/src/solana/mailer-client.js +985 -0
- package/dist/unified-esm/src/solana/mailer-client.js.map +1 -0
- package/dist/unified-esm/src/solana/types.d.ts +28 -0
- package/dist/unified-esm/src/solana/types.d.ts.map +1 -0
- package/dist/unified-esm/src/solana/types.js +16 -0
- package/dist/unified-esm/src/solana/types.js.map +1 -0
- package/dist/unified-esm/src/unified/index.d.ts +4 -0
- package/dist/unified-esm/src/unified/index.d.ts.map +1 -0
- package/dist/unified-esm/src/unified/index.js +4 -0
- package/dist/unified-esm/src/unified/index.js.map +1 -0
- package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +173 -0
- package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -0
- package/dist/unified-esm/src/unified/onchain-mailer-client.js +1011 -0
- package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -0
- package/dist/unified-esm/src/unified/types.d.ts +47 -0
- package/dist/unified-esm/src/unified/types.d.ts.map +1 -0
- package/dist/unified-esm/src/unified/types.js +2 -0
- package/dist/unified-esm/src/unified/types.js.map +1 -0
- package/dist/unified-esm/src/unified/wallet-detector.d.ts +28 -0
- package/dist/unified-esm/src/unified/wallet-detector.d.ts.map +1 -0
- package/dist/unified-esm/src/unified/wallet-detector.js +59 -0
- package/dist/unified-esm/src/unified/wallet-detector.js.map +1 -0
- package/dist/unified-esm/src/utils/chain-config.d.ts +75 -0
- package/dist/unified-esm/src/utils/chain-config.d.ts.map +1 -0
- package/dist/unified-esm/src/utils/chain-config.js +199 -0
- package/dist/unified-esm/src/utils/chain-config.js.map +1 -0
- package/dist/unified-esm/src/utils/currency.d.ts +26 -0
- package/dist/unified-esm/src/utils/currency.d.ts.map +1 -0
- package/dist/unified-esm/src/utils/currency.js +31 -0
- package/dist/unified-esm/src/utils/currency.js.map +1 -0
- package/dist/unified-esm/src/utils/index.d.ts +4 -0
- package/dist/unified-esm/src/utils/index.d.ts.map +1 -0
- package/dist/unified-esm/src/utils/index.js +4 -0
- package/dist/unified-esm/src/utils/index.js.map +1 -0
- package/dist/unified-esm/src/utils/validation.d.ts +10 -0
- package/dist/unified-esm/src/utils/validation.d.ts.map +1 -0
- package/dist/unified-esm/src/utils/validation.js +96 -0
- package/dist/unified-esm/src/utils/validation.js.map +1 -0
- package/dist/unified-esm/typechain-types/Mailer.d.ts +698 -0
- package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/Mailer.js +2 -0
- package/dist/unified-esm/typechain-types/Mailer.js.map +1 -0
- package/dist/unified-esm/typechain-types/MockUSDC.d.ts +118 -0
- package/dist/unified-esm/typechain-types/MockUSDC.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/MockUSDC.js +2 -0
- package/dist/unified-esm/typechain-types/MockUSDC.js.map +1 -0
- package/dist/unified-esm/typechain-types/common.d.ts +51 -0
- package/dist/unified-esm/typechain-types/common.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/common.js +2 -0
- package/dist/unified-esm/typechain-types/common.js.map +1 -0
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +875 -0
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +1121 -0
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -0
- package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.d.ts +193 -0
- package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.js +259 -0
- package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.js.map +1 -0
- package/dist/unified-esm/typechain-types/factories/index.d.ts +4 -0
- package/dist/unified-esm/typechain-types/factories/index.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/factories/index.js +7 -0
- package/dist/unified-esm/typechain-types/factories/index.js.map +1 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.d.ts +80 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.js +112 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.js.map +1 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/index.d.ts +2 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/index.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/index.js +5 -0
- package/dist/unified-esm/typechain-types/factories/interfaces/index.js.map +1 -0
- package/dist/unified-esm/typechain-types/index.d.ts +10 -0
- package/dist/unified-esm/typechain-types/index.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/index.js +5 -0
- package/dist/unified-esm/typechain-types/index.js.map +1 -0
- package/dist/unified-esm/typechain-types/interfaces/IERC20.d.ts +70 -0
- package/dist/unified-esm/typechain-types/interfaces/IERC20.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/interfaces/IERC20.js +2 -0
- package/dist/unified-esm/typechain-types/interfaces/IERC20.js.map +1 -0
- package/dist/unified-esm/typechain-types/interfaces/index.d.ts +2 -0
- package/dist/unified-esm/typechain-types/interfaces/index.d.ts.map +1 -0
- package/dist/unified-esm/typechain-types/interfaces/index.js +2 -0
- package/dist/unified-esm/typechain-types/interfaces/index.js.map +1 -0
- package/package.json +250 -0
- package/programs/mailer/Cargo.toml +29 -0
- package/programs/mailer/src/lib.rs +2034 -0
- package/programs/mailer/tests/integration_tests.rs +1236 -0
- package/typechain-types/Mailer.ts +1393 -0
- package/typechain-types/MockUSDC.ts +236 -0
- package/typechain-types/common.ts +131 -0
- package/typechain-types/factories/Mailer__factory.ts +1157 -0
- package/typechain-types/factories/MockUSDC__factory.ts +284 -0
- package/typechain-types/factories/index.ts +6 -0
- package/typechain-types/factories/interfaces/IERC20__factory.ts +115 -0
- package/typechain-types/factories/interfaces/index.ts +4 -0
- package/typechain-types/hardhat.d.ts +99 -0
- package/typechain-types/index.ts +12 -0
- package/typechain-types/interfaces/IERC20.ts +148 -0
- package/typechain-types/interfaces/index.ts +4 -0
|
@@ -0,0 +1,985 @@
|
|
|
1
|
+
import { PublicKey, Transaction, TransactionInstruction, SystemProgram, ComputeBudgetProgram, } from '@solana/web3.js';
|
|
2
|
+
import { TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, createAssociatedTokenAccountInstruction, } from '@solana/spl-token';
|
|
3
|
+
/**
|
|
4
|
+
* Native Solana Program instruction data structures
|
|
5
|
+
*/
|
|
6
|
+
// Instruction data encoding functions
|
|
7
|
+
function encodeInitialize(usdcMint) {
|
|
8
|
+
const data = Buffer.alloc(1 + 32);
|
|
9
|
+
data.writeUInt8(InstructionType.Initialize, 0);
|
|
10
|
+
usdcMint.toBuffer().copy(data, 1);
|
|
11
|
+
return data;
|
|
12
|
+
}
|
|
13
|
+
function encodeSend(to, subject, body, revenueShareToReceiver, resolveSenderToName = false) {
|
|
14
|
+
const subjectBytes = Buffer.from(subject, 'utf8');
|
|
15
|
+
const bodyBytes = Buffer.from(body, 'utf8');
|
|
16
|
+
const data = Buffer.alloc(1 + 32 + 4 + subjectBytes.length + 4 + bodyBytes.length + 1 + 1);
|
|
17
|
+
let offset = 0;
|
|
18
|
+
data.writeUInt8(InstructionType.Send, offset);
|
|
19
|
+
offset += 1;
|
|
20
|
+
to.toBuffer().copy(data, offset);
|
|
21
|
+
offset += 32;
|
|
22
|
+
data.writeUInt32LE(subjectBytes.length, offset);
|
|
23
|
+
offset += 4;
|
|
24
|
+
subjectBytes.copy(data, offset);
|
|
25
|
+
offset += subjectBytes.length;
|
|
26
|
+
data.writeUInt32LE(bodyBytes.length, offset);
|
|
27
|
+
offset += 4;
|
|
28
|
+
bodyBytes.copy(data, offset);
|
|
29
|
+
offset += bodyBytes.length;
|
|
30
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
31
|
+
offset += 1;
|
|
32
|
+
data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
function encodeSendPrepared(to, mailId, revenueShareToReceiver, resolveSenderToName = false) {
|
|
36
|
+
const mailIdBytes = Buffer.from(mailId, 'utf8');
|
|
37
|
+
const data = Buffer.alloc(1 + 32 + 4 + mailIdBytes.length + 1 + 1);
|
|
38
|
+
let offset = 0;
|
|
39
|
+
data.writeUInt8(InstructionType.SendPrepared, offset);
|
|
40
|
+
offset += 1;
|
|
41
|
+
to.toBuffer().copy(data, offset);
|
|
42
|
+
offset += 32;
|
|
43
|
+
data.writeUInt32LE(mailIdBytes.length, offset);
|
|
44
|
+
offset += 4;
|
|
45
|
+
mailIdBytes.copy(data, offset);
|
|
46
|
+
offset += mailIdBytes.length;
|
|
47
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
48
|
+
offset += 1;
|
|
49
|
+
data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
function encodeSendToEmail(toEmail, subject, body) {
|
|
53
|
+
const emailBytes = Buffer.from(toEmail, 'utf8');
|
|
54
|
+
const subjectBytes = Buffer.from(subject, 'utf8');
|
|
55
|
+
const bodyBytes = Buffer.from(body, 'utf8');
|
|
56
|
+
const data = Buffer.alloc(1 + 4 + emailBytes.length + 4 + subjectBytes.length + 4 + bodyBytes.length);
|
|
57
|
+
let offset = 0;
|
|
58
|
+
data.writeUInt8(InstructionType.SendToEmail, offset);
|
|
59
|
+
offset += 1;
|
|
60
|
+
data.writeUInt32LE(emailBytes.length, offset);
|
|
61
|
+
offset += 4;
|
|
62
|
+
emailBytes.copy(data, offset);
|
|
63
|
+
offset += emailBytes.length;
|
|
64
|
+
data.writeUInt32LE(subjectBytes.length, offset);
|
|
65
|
+
offset += 4;
|
|
66
|
+
subjectBytes.copy(data, offset);
|
|
67
|
+
offset += subjectBytes.length;
|
|
68
|
+
data.writeUInt32LE(bodyBytes.length, offset);
|
|
69
|
+
offset += 4;
|
|
70
|
+
bodyBytes.copy(data, offset);
|
|
71
|
+
return data;
|
|
72
|
+
}
|
|
73
|
+
function encodeSendPreparedToEmail(toEmail, mailId) {
|
|
74
|
+
const emailBytes = Buffer.from(toEmail, 'utf8');
|
|
75
|
+
const mailIdBytes = Buffer.from(mailId, 'utf8');
|
|
76
|
+
const data = Buffer.alloc(1 + 4 + emailBytes.length + 4 + mailIdBytes.length);
|
|
77
|
+
let offset = 0;
|
|
78
|
+
data.writeUInt8(InstructionType.SendPreparedToEmail, offset);
|
|
79
|
+
offset += 1;
|
|
80
|
+
data.writeUInt32LE(emailBytes.length, offset);
|
|
81
|
+
offset += 4;
|
|
82
|
+
emailBytes.copy(data, offset);
|
|
83
|
+
offset += emailBytes.length;
|
|
84
|
+
data.writeUInt32LE(mailIdBytes.length, offset);
|
|
85
|
+
offset += 4;
|
|
86
|
+
mailIdBytes.copy(data, offset);
|
|
87
|
+
return data;
|
|
88
|
+
}
|
|
89
|
+
function encodeSendThroughWebhook(to, webhookId, revenueShareToReceiver, resolveSenderToName = false) {
|
|
90
|
+
const webhookBytes = Buffer.from(webhookId, 'utf8');
|
|
91
|
+
const data = Buffer.alloc(1 + 32 + 4 + webhookBytes.length + 1 + 1);
|
|
92
|
+
let offset = 0;
|
|
93
|
+
data.writeUInt8(InstructionType.SendThroughWebhook, offset);
|
|
94
|
+
offset += 1;
|
|
95
|
+
to.toBuffer().copy(data, offset);
|
|
96
|
+
offset += 32;
|
|
97
|
+
data.writeUInt32LE(webhookBytes.length, offset);
|
|
98
|
+
offset += 4;
|
|
99
|
+
webhookBytes.copy(data, offset);
|
|
100
|
+
offset += webhookBytes.length;
|
|
101
|
+
data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
|
|
102
|
+
offset += 1;
|
|
103
|
+
data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
|
|
104
|
+
return data;
|
|
105
|
+
}
|
|
106
|
+
function encodeSimpleInstruction(instructionType) {
|
|
107
|
+
const data = Buffer.alloc(1);
|
|
108
|
+
data.writeUInt8(instructionType, 0);
|
|
109
|
+
return data;
|
|
110
|
+
}
|
|
111
|
+
function encodeSetFee(newFee) {
|
|
112
|
+
const data = Buffer.alloc(1 + 8);
|
|
113
|
+
data.writeUInt8(InstructionType.SetFee, 0);
|
|
114
|
+
data.writeBigUInt64LE(newFee, 1);
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
117
|
+
function encodeSetDelegationFee(newFee) {
|
|
118
|
+
const data = Buffer.alloc(1 + 8);
|
|
119
|
+
data.writeUInt8(InstructionType.SetDelegationFee, 0);
|
|
120
|
+
data.writeBigUInt64LE(newFee, 1);
|
|
121
|
+
return data;
|
|
122
|
+
}
|
|
123
|
+
function encodeSetCustomFeePercentage(account, percentage) {
|
|
124
|
+
const data = Buffer.alloc(1 + 32 + 1);
|
|
125
|
+
data.writeUInt8(InstructionType.SetCustomFeePercentage, 0);
|
|
126
|
+
account.toBuffer().copy(data, 1);
|
|
127
|
+
data.writeUInt8(percentage, 33);
|
|
128
|
+
return data;
|
|
129
|
+
}
|
|
130
|
+
function encodeClearCustomFeePercentage(account) {
|
|
131
|
+
const data = Buffer.alloc(1 + 32);
|
|
132
|
+
data.writeUInt8(InstructionType.ClearCustomFeePercentage, 0);
|
|
133
|
+
account.toBuffer().copy(data, 1);
|
|
134
|
+
return data;
|
|
135
|
+
}
|
|
136
|
+
function encodeDelegateTo(delegate) {
|
|
137
|
+
if (!delegate) {
|
|
138
|
+
// Clear delegation - just send the instruction type and a null option
|
|
139
|
+
const data = Buffer.alloc(1 + 1);
|
|
140
|
+
data.writeUInt8(InstructionType.DelegateTo, 0);
|
|
141
|
+
data.writeUInt8(0, 1); // Option::None
|
|
142
|
+
return data;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Set delegation - send instruction type, Some option, and pubkey
|
|
146
|
+
const data = Buffer.alloc(1 + 1 + 32);
|
|
147
|
+
data.writeUInt8(InstructionType.DelegateTo, 0);
|
|
148
|
+
data.writeUInt8(1, 1); // Option::Some
|
|
149
|
+
delegate.toBuffer().copy(data, 2);
|
|
150
|
+
return data;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function encodeClaimExpiredShares(recipient) {
|
|
154
|
+
const data = Buffer.alloc(1 + 32);
|
|
155
|
+
data.writeUInt8(InstructionType.ClaimExpiredShares, 0);
|
|
156
|
+
recipient.toBuffer().copy(data, 1);
|
|
157
|
+
return data;
|
|
158
|
+
}
|
|
159
|
+
// Account data parsing functions
|
|
160
|
+
function parseMailerState(data) {
|
|
161
|
+
let offset = 0;
|
|
162
|
+
const owner = new PublicKey(data.slice(offset, offset + 32));
|
|
163
|
+
offset += 32;
|
|
164
|
+
const usdcMint = new PublicKey(data.slice(offset, offset + 32));
|
|
165
|
+
offset += 32;
|
|
166
|
+
const sendFee = data.readBigUInt64LE(offset);
|
|
167
|
+
offset += 8;
|
|
168
|
+
const delegationFee = data.readBigUInt64LE(offset);
|
|
169
|
+
offset += 8;
|
|
170
|
+
const ownerClaimable = data.readBigUInt64LE(offset);
|
|
171
|
+
offset += 8;
|
|
172
|
+
const paused = data.readUInt8(offset) === 1;
|
|
173
|
+
offset += 1;
|
|
174
|
+
const bump = data.readUInt8(offset);
|
|
175
|
+
return {
|
|
176
|
+
owner,
|
|
177
|
+
usdc_mint: usdcMint,
|
|
178
|
+
send_fee: sendFee,
|
|
179
|
+
delegation_fee: delegationFee,
|
|
180
|
+
owner_claimable: ownerClaimable,
|
|
181
|
+
paused,
|
|
182
|
+
bump,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function parseRecipientClaim(data) {
|
|
186
|
+
let offset = 0;
|
|
187
|
+
const recipient = new PublicKey(data.slice(offset, offset + 32));
|
|
188
|
+
offset += 32;
|
|
189
|
+
const amount = data.readBigUInt64LE(offset);
|
|
190
|
+
offset += 8;
|
|
191
|
+
const timestamp = data.readBigInt64LE(offset);
|
|
192
|
+
offset += 8;
|
|
193
|
+
const bump = data.readUInt8(offset);
|
|
194
|
+
return {
|
|
195
|
+
recipient,
|
|
196
|
+
amount,
|
|
197
|
+
timestamp,
|
|
198
|
+
bump,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function parseDelegation(data) {
|
|
202
|
+
let offset = 0;
|
|
203
|
+
const delegator = new PublicKey(data.slice(offset, offset + 32));
|
|
204
|
+
offset += 32;
|
|
205
|
+
const hasDelegate = data.readUInt8(offset) === 1;
|
|
206
|
+
offset += 1;
|
|
207
|
+
const delegate = hasDelegate
|
|
208
|
+
? new PublicKey(data.slice(offset, offset + 32))
|
|
209
|
+
: null;
|
|
210
|
+
if (hasDelegate)
|
|
211
|
+
offset += 32;
|
|
212
|
+
const bump = data.readUInt8(offset);
|
|
213
|
+
return {
|
|
214
|
+
delegator,
|
|
215
|
+
delegate,
|
|
216
|
+
bump,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function parseFeeDiscount(data) {
|
|
220
|
+
let offset = 0;
|
|
221
|
+
const account = new PublicKey(data.slice(offset, offset + 32));
|
|
222
|
+
offset += 32;
|
|
223
|
+
const discount = data.readUInt8(offset);
|
|
224
|
+
offset += 1;
|
|
225
|
+
const bump = data.readUInt8(offset);
|
|
226
|
+
return {
|
|
227
|
+
account,
|
|
228
|
+
discount,
|
|
229
|
+
bump,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
var InstructionType;
|
|
233
|
+
(function (InstructionType) {
|
|
234
|
+
InstructionType[InstructionType["Initialize"] = 0] = "Initialize";
|
|
235
|
+
InstructionType[InstructionType["Send"] = 1] = "Send";
|
|
236
|
+
InstructionType[InstructionType["SendPrepared"] = 2] = "SendPrepared";
|
|
237
|
+
InstructionType[InstructionType["SendToEmail"] = 3] = "SendToEmail";
|
|
238
|
+
InstructionType[InstructionType["SendPreparedToEmail"] = 4] = "SendPreparedToEmail";
|
|
239
|
+
InstructionType[InstructionType["SendThroughWebhook"] = 5] = "SendThroughWebhook";
|
|
240
|
+
InstructionType[InstructionType["ClaimRecipientShare"] = 6] = "ClaimRecipientShare";
|
|
241
|
+
InstructionType[InstructionType["ClaimOwnerShare"] = 7] = "ClaimOwnerShare";
|
|
242
|
+
InstructionType[InstructionType["SetFee"] = 8] = "SetFee";
|
|
243
|
+
InstructionType[InstructionType["DelegateTo"] = 9] = "DelegateTo";
|
|
244
|
+
InstructionType[InstructionType["RejectDelegation"] = 10] = "RejectDelegation";
|
|
245
|
+
InstructionType[InstructionType["SetDelegationFee"] = 11] = "SetDelegationFee";
|
|
246
|
+
InstructionType[InstructionType["SetCustomFeePercentage"] = 12] = "SetCustomFeePercentage";
|
|
247
|
+
InstructionType[InstructionType["ClearCustomFeePercentage"] = 13] = "ClearCustomFeePercentage";
|
|
248
|
+
InstructionType[InstructionType["Pause"] = 14] = "Pause";
|
|
249
|
+
InstructionType[InstructionType["Unpause"] = 15] = "Unpause";
|
|
250
|
+
InstructionType[InstructionType["DistributeClaimableFunds"] = 16] = "DistributeClaimableFunds";
|
|
251
|
+
InstructionType[InstructionType["ClaimExpiredShares"] = 17] = "ClaimExpiredShares";
|
|
252
|
+
InstructionType[InstructionType["EmergencyUnpause"] = 18] = "EmergencyUnpause";
|
|
253
|
+
})(InstructionType || (InstructionType = {}));
|
|
254
|
+
/**
|
|
255
|
+
* @class MailerClient
|
|
256
|
+
* @description Native Solana program client for the Mailer program
|
|
257
|
+
* @notice Provides easy-to-use methods for sending messages with USDC fees and revenue sharing
|
|
258
|
+
*
|
|
259
|
+
* ## Key Features:
|
|
260
|
+
* - **Priority Messages**: Full fee (0.1 USDC) with 90% revenue share to recipient
|
|
261
|
+
* - **Standard Messages**: 10% fee only (0.01 USDC) with no revenue share
|
|
262
|
+
* - **Revenue Claims**: 60-day claim period for priority message revenue shares
|
|
263
|
+
* - **Delegation Management**: Delegate message handling with rejection capability
|
|
264
|
+
*
|
|
265
|
+
* ## Usage Examples:
|
|
266
|
+
* ```typescript
|
|
267
|
+
* // Connect to existing deployed program
|
|
268
|
+
* const connection = new Connection('https://api.devnet.solana.com');
|
|
269
|
+
* const wallet = new WalletAdapter(keypair);
|
|
270
|
+
* const programId = new PublicKey('9FLkBDGpZBcR8LMsQ7MwwV6X9P4TDFgN3DeRh5qYyHJF');
|
|
271
|
+
* const usdcMint = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
|
|
272
|
+
* const client = new MailerClient(connection, wallet, programId, usdcMint);
|
|
273
|
+
*
|
|
274
|
+
* // Send message with revenue sharing to recipient
|
|
275
|
+
* await client.send('recipient-address', 'Subject', 'Message body', true);
|
|
276
|
+
*
|
|
277
|
+
* // Claim your revenue share within 60 days (as recipient)
|
|
278
|
+
* await client.claimRecipientShare();
|
|
279
|
+
*
|
|
280
|
+
* // Check claimable amount
|
|
281
|
+
* const info = await client.getRecipientClaimable();
|
|
282
|
+
* if (info) console.log(`Claimable: ${formatUSDC(info.amount)} USDC`);
|
|
283
|
+
* ```
|
|
284
|
+
*
|
|
285
|
+
* @author Mailer Team
|
|
286
|
+
* @version 2.0.0 - Native Solana Program (no Anchor)
|
|
287
|
+
*/
|
|
288
|
+
export class MailerClient {
|
|
289
|
+
constructor(connection, wallet, programId, usdcMint) {
|
|
290
|
+
this.defaultComputeUnitMultiplier = 1.2; // 20% buffer by default
|
|
291
|
+
this.connection = connection;
|
|
292
|
+
this.wallet = wallet;
|
|
293
|
+
this.programId = programId;
|
|
294
|
+
this.usdcMint = usdcMint;
|
|
295
|
+
// Derive the mailer state PDA
|
|
296
|
+
const [mailerPda, bump] = PublicKey.findProgramAddressSync([Buffer.from('mailer')], this.programId);
|
|
297
|
+
this.mailerStatePda = mailerPda;
|
|
298
|
+
this.mailerBump = bump;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Optimize compute units for a transaction
|
|
302
|
+
* @param transaction Transaction to optimize
|
|
303
|
+
* @param options Compute unit options
|
|
304
|
+
* @returns Optimized transaction with compute budget instructions
|
|
305
|
+
*/
|
|
306
|
+
async optimizeComputeUnits(transaction, options) {
|
|
307
|
+
// Skip if explicitly disabled
|
|
308
|
+
if (options?.skipComputeUnits) {
|
|
309
|
+
return { transaction };
|
|
310
|
+
}
|
|
311
|
+
let simulatedUnits;
|
|
312
|
+
let computeUnitLimit = options?.computeUnitLimit;
|
|
313
|
+
// Auto-optimize by simulating transaction
|
|
314
|
+
if (options?.autoOptimize && !computeUnitLimit) {
|
|
315
|
+
try {
|
|
316
|
+
// Set a high limit for simulation
|
|
317
|
+
const simTransaction = new Transaction().add(...transaction.instructions);
|
|
318
|
+
simTransaction.add(ComputeBudgetProgram.setComputeUnitLimit({
|
|
319
|
+
units: 1400000, // Max for simulation
|
|
320
|
+
}));
|
|
321
|
+
simTransaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
322
|
+
simTransaction.feePayer = this.wallet.publicKey;
|
|
323
|
+
const simulation = await this.connection.simulateTransaction(simTransaction);
|
|
324
|
+
if (simulation.value.err === null && simulation.value.unitsConsumed) {
|
|
325
|
+
simulatedUnits = simulation.value.unitsConsumed;
|
|
326
|
+
const multiplier = options.computeUnitMultiplier ?? this.defaultComputeUnitMultiplier;
|
|
327
|
+
computeUnitLimit = Math.min(Math.ceil(simulatedUnits * multiplier), 1400000 // Max compute units
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
console.warn('Failed to simulate transaction for compute unit optimization:', error);
|
|
333
|
+
// Fall back to default or specified limit
|
|
334
|
+
computeUnitLimit = computeUnitLimit ?? 200000;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// Create new transaction with compute budget instructions prepended
|
|
338
|
+
const optimizedTx = new Transaction();
|
|
339
|
+
// Add compute unit limit if specified or auto-optimized
|
|
340
|
+
if (computeUnitLimit) {
|
|
341
|
+
optimizedTx.add(ComputeBudgetProgram.setComputeUnitLimit({
|
|
342
|
+
units: computeUnitLimit,
|
|
343
|
+
}));
|
|
344
|
+
}
|
|
345
|
+
// Add priority fee if specified
|
|
346
|
+
if (options?.computeUnitPrice) {
|
|
347
|
+
optimizedTx.add(ComputeBudgetProgram.setComputeUnitPrice({
|
|
348
|
+
microLamports: options.computeUnitPrice,
|
|
349
|
+
}));
|
|
350
|
+
}
|
|
351
|
+
// Add original instructions
|
|
352
|
+
optimizedTx.add(...transaction.instructions);
|
|
353
|
+
return {
|
|
354
|
+
transaction: optimizedTx,
|
|
355
|
+
simulatedUnits,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Initialize the mailer program (owner only)
|
|
360
|
+
* @param computeOptions Compute unit optimization options
|
|
361
|
+
*/
|
|
362
|
+
async initialize(computeOptions) {
|
|
363
|
+
const instruction = new TransactionInstruction({
|
|
364
|
+
keys: [
|
|
365
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
366
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
367
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
368
|
+
],
|
|
369
|
+
programId: this.programId,
|
|
370
|
+
data: encodeInitialize(this.usdcMint),
|
|
371
|
+
});
|
|
372
|
+
const transaction = new Transaction().add(instruction);
|
|
373
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Send a message with optional revenue sharing
|
|
377
|
+
* @param to Recipient's public key or address string who receives message and potential revenue share
|
|
378
|
+
* @param subject Message subject
|
|
379
|
+
* @param body Message body
|
|
380
|
+
* @param revenueShareToReceiver If true, recipient gets 90% revenue share; if false, no revenue share
|
|
381
|
+
* @param resolveSenderToName If true, resolve sender address to name via off-chain service
|
|
382
|
+
* @param computeOptions Compute unit optimization options
|
|
383
|
+
* @returns Transaction result with signature and compute details
|
|
384
|
+
*/
|
|
385
|
+
async send(to, subject, body, revenueShareToReceiver = false, resolveSenderToName = false, computeOptions) {
|
|
386
|
+
const recipientKey = typeof to === 'string' ? new PublicKey(to) : to;
|
|
387
|
+
// Derive recipient claim PDA
|
|
388
|
+
const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
389
|
+
// Get associated token accounts
|
|
390
|
+
const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
391
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
392
|
+
// Check if accounts need to be created
|
|
393
|
+
const instructions = [];
|
|
394
|
+
// Check if mailer token account exists
|
|
395
|
+
const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
|
|
396
|
+
if (!mailerTokenInfo) {
|
|
397
|
+
instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
|
|
398
|
+
}
|
|
399
|
+
// Add the send instruction
|
|
400
|
+
const sendInstruction = new TransactionInstruction({
|
|
401
|
+
keys: [
|
|
402
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
403
|
+
{ pubkey: recipientClaimPda, isSigner: false, isWritable: true },
|
|
404
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
405
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
406
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
407
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
408
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
409
|
+
],
|
|
410
|
+
programId: this.programId,
|
|
411
|
+
data: encodeSend(recipientKey, subject, body, revenueShareToReceiver, resolveSenderToName),
|
|
412
|
+
});
|
|
413
|
+
instructions.push(sendInstruction);
|
|
414
|
+
const transaction = new Transaction().add(...instructions);
|
|
415
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Claim recipient share of revenue
|
|
419
|
+
* @returns Transaction result
|
|
420
|
+
*/
|
|
421
|
+
async claimRecipientShare(computeOptions) {
|
|
422
|
+
const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), this.wallet.publicKey.toBuffer()], this.programId);
|
|
423
|
+
const recipientTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
424
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
425
|
+
const instruction = new TransactionInstruction({
|
|
426
|
+
keys: [
|
|
427
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
428
|
+
{ pubkey: recipientClaimPda, isSigner: false, isWritable: true },
|
|
429
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
430
|
+
{ pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
|
|
431
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
432
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
433
|
+
],
|
|
434
|
+
programId: this.programId,
|
|
435
|
+
data: encodeSimpleInstruction(InstructionType.ClaimRecipientShare),
|
|
436
|
+
});
|
|
437
|
+
const transaction = new Transaction().add(instruction);
|
|
438
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Claim owner share of fees (owner only)
|
|
442
|
+
* @returns Transaction result
|
|
443
|
+
*/
|
|
444
|
+
async claimOwnerShare(computeOptions) {
|
|
445
|
+
const ownerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
446
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
447
|
+
const instruction = new TransactionInstruction({
|
|
448
|
+
keys: [
|
|
449
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
450
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
451
|
+
{ pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
|
|
452
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
453
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
454
|
+
],
|
|
455
|
+
programId: this.programId,
|
|
456
|
+
data: encodeSimpleInstruction(InstructionType.ClaimOwnerShare),
|
|
457
|
+
});
|
|
458
|
+
const transaction = new Transaction().add(instruction);
|
|
459
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Claim expired recipient shares and move them under owner control
|
|
463
|
+
* @param recipient Recipient whose expired shares to reclaim
|
|
464
|
+
* @param options Transaction confirm options
|
|
465
|
+
* @returns Transaction signature
|
|
466
|
+
*/
|
|
467
|
+
async claimExpiredShares(recipient, options, computeOptions) {
|
|
468
|
+
const recipientKey = typeof recipient === 'string' ? new PublicKey(recipient) : recipient;
|
|
469
|
+
const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
470
|
+
const instruction = new TransactionInstruction({
|
|
471
|
+
keys: [
|
|
472
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
473
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
474
|
+
{ pubkey: recipientClaimPda, isSigner: false, isWritable: true },
|
|
475
|
+
],
|
|
476
|
+
programId: this.programId,
|
|
477
|
+
data: encodeClaimExpiredShares(recipientKey),
|
|
478
|
+
});
|
|
479
|
+
const transaction = new Transaction().add(instruction);
|
|
480
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Delegate message handling to another address
|
|
484
|
+
* @param delegate Address to delegate to, or null to clear delegation
|
|
485
|
+
* @returns Transaction signature
|
|
486
|
+
*/
|
|
487
|
+
async delegateTo(delegate, computeOptions) {
|
|
488
|
+
const delegateKey = delegate
|
|
489
|
+
? typeof delegate === 'string'
|
|
490
|
+
? new PublicKey(delegate)
|
|
491
|
+
: delegate
|
|
492
|
+
: null;
|
|
493
|
+
const [delegationPda] = PublicKey.findProgramAddressSync([Buffer.from('delegation'), this.wallet.publicKey.toBuffer()], this.programId);
|
|
494
|
+
const delegatorTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
495
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
496
|
+
const instruction = new TransactionInstruction({
|
|
497
|
+
keys: [
|
|
498
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
499
|
+
{ pubkey: delegationPda, isSigner: false, isWritable: true },
|
|
500
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
501
|
+
{ pubkey: delegatorTokenAccount, isSigner: false, isWritable: true },
|
|
502
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
503
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
504
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
505
|
+
],
|
|
506
|
+
programId: this.programId,
|
|
507
|
+
data: encodeDelegateTo(delegateKey),
|
|
508
|
+
});
|
|
509
|
+
const transaction = new Transaction().add(instruction);
|
|
510
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Reject a delegation made to you
|
|
514
|
+
* @param delegator Address that delegated to you
|
|
515
|
+
* @returns Transaction signature
|
|
516
|
+
*/
|
|
517
|
+
async rejectDelegation(delegator, computeOptions) {
|
|
518
|
+
const delegatorKey = typeof delegator === 'string' ? new PublicKey(delegator) : delegator;
|
|
519
|
+
const [delegationPda] = PublicKey.findProgramAddressSync([Buffer.from('delegation'), delegatorKey.toBuffer()], this.programId);
|
|
520
|
+
const instruction = new TransactionInstruction({
|
|
521
|
+
keys: [
|
|
522
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
523
|
+
{ pubkey: delegationPda, isSigner: false, isWritable: true },
|
|
524
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
525
|
+
],
|
|
526
|
+
programId: this.programId,
|
|
527
|
+
data: encodeSimpleInstruction(InstructionType.RejectDelegation),
|
|
528
|
+
});
|
|
529
|
+
const transaction = new Transaction().add(instruction);
|
|
530
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Set the send fee (owner only)
|
|
534
|
+
* @param newFee New fee in USDC micro-units (6 decimals)
|
|
535
|
+
* @param computeOptions Compute unit optimization options
|
|
536
|
+
* @returns Transaction result
|
|
537
|
+
*/
|
|
538
|
+
async setFee(newFee, computeOptions) {
|
|
539
|
+
const instruction = new TransactionInstruction({
|
|
540
|
+
keys: [
|
|
541
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
542
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
543
|
+
],
|
|
544
|
+
programId: this.programId,
|
|
545
|
+
data: encodeSetFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
|
|
546
|
+
});
|
|
547
|
+
const transaction = new Transaction().add(instruction);
|
|
548
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Set the delegation fee (owner only)
|
|
552
|
+
* @param newFee New delegation fee in USDC micro-units (6 decimals)
|
|
553
|
+
* @returns Transaction signature
|
|
554
|
+
*/
|
|
555
|
+
async setDelegationFee(newFee, computeOptions) {
|
|
556
|
+
const instruction = new TransactionInstruction({
|
|
557
|
+
keys: [
|
|
558
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
559
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
560
|
+
],
|
|
561
|
+
programId: this.programId,
|
|
562
|
+
data: encodeSetDelegationFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
|
|
563
|
+
});
|
|
564
|
+
const transaction = new Transaction().add(instruction);
|
|
565
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
566
|
+
}
|
|
567
|
+
async setCustomFeePercentage(account, percentage, payer, computeOptions) {
|
|
568
|
+
const normalizedPercentage = Math.trunc(percentage);
|
|
569
|
+
if (normalizedPercentage < 0 || normalizedPercentage > 100) {
|
|
570
|
+
throw new Error('Percentage must be between 0 and 100');
|
|
571
|
+
}
|
|
572
|
+
const accountKey = typeof account === 'string' ? new PublicKey(account) : account;
|
|
573
|
+
const payerKey = payer
|
|
574
|
+
? typeof payer === 'string'
|
|
575
|
+
? new PublicKey(payer)
|
|
576
|
+
: payer
|
|
577
|
+
: this.wallet.publicKey;
|
|
578
|
+
const [discountPda] = PublicKey.findProgramAddressSync([Buffer.from('discount'), accountKey.toBuffer()], this.programId);
|
|
579
|
+
const instruction = new TransactionInstruction({
|
|
580
|
+
keys: [
|
|
581
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
582
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
583
|
+
{ pubkey: discountPda, isSigner: false, isWritable: true },
|
|
584
|
+
{ pubkey: accountKey, isSigner: false, isWritable: false },
|
|
585
|
+
{ pubkey: payerKey, isSigner: true, isWritable: true },
|
|
586
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
587
|
+
],
|
|
588
|
+
programId: this.programId,
|
|
589
|
+
data: encodeSetCustomFeePercentage(accountKey, normalizedPercentage),
|
|
590
|
+
});
|
|
591
|
+
const transaction = new Transaction().add(instruction);
|
|
592
|
+
return this.sendTransaction(transaction, undefined, computeOptions);
|
|
593
|
+
}
|
|
594
|
+
async clearCustomFeePercentage(account, computeOptions) {
|
|
595
|
+
const accountKey = typeof account === 'string' ? new PublicKey(account) : account;
|
|
596
|
+
const [discountPda] = PublicKey.findProgramAddressSync([Buffer.from('discount'), accountKey.toBuffer()], this.programId);
|
|
597
|
+
const instruction = new TransactionInstruction({
|
|
598
|
+
keys: [
|
|
599
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
600
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
601
|
+
{ pubkey: discountPda, isSigner: false, isWritable: true },
|
|
602
|
+
],
|
|
603
|
+
programId: this.programId,
|
|
604
|
+
data: encodeClearCustomFeePercentage(accountKey),
|
|
605
|
+
});
|
|
606
|
+
const transaction = new Transaction().add(instruction);
|
|
607
|
+
return this.sendTransaction(transaction, undefined, computeOptions);
|
|
608
|
+
}
|
|
609
|
+
async getCustomFeePercentage(account) {
|
|
610
|
+
const accountKey = typeof account === 'string' ? new PublicKey(account) : account;
|
|
611
|
+
const [discountPda] = PublicKey.findProgramAddressSync([Buffer.from('discount'), accountKey.toBuffer()], this.programId);
|
|
612
|
+
const accountInfo = await this.connection.getAccountInfo(discountPda);
|
|
613
|
+
if (!accountInfo) {
|
|
614
|
+
return 100;
|
|
615
|
+
}
|
|
616
|
+
const discountState = parseFeeDiscount(accountInfo.data);
|
|
617
|
+
return 100 - discountState.discount;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Get current fees from the mailer state
|
|
621
|
+
* @returns MailerFees object with current fees
|
|
622
|
+
*/
|
|
623
|
+
async getFees() {
|
|
624
|
+
const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
|
|
625
|
+
if (!accountInfo) {
|
|
626
|
+
throw new Error('Mailer state account not found - program not initialized');
|
|
627
|
+
}
|
|
628
|
+
const stateData = parseMailerState(accountInfo.data);
|
|
629
|
+
return {
|
|
630
|
+
sendFee: Number(stateData.send_fee),
|
|
631
|
+
delegationFee: Number(stateData.delegation_fee),
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Get recipient claimable information
|
|
636
|
+
* @param recipient Optional recipient address, defaults to wallet address
|
|
637
|
+
* @returns ClaimableInfo or null if no claimable amount
|
|
638
|
+
*/
|
|
639
|
+
async getRecipientClaimable(recipient) {
|
|
640
|
+
const recipientKey = recipient || this.wallet.publicKey;
|
|
641
|
+
const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
642
|
+
const accountInfo = await this.connection.getAccountInfo(recipientClaimPda);
|
|
643
|
+
if (!accountInfo) {
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
const claimData = parseRecipientClaim(accountInfo.data);
|
|
647
|
+
// Check if claim period has expired (60 days)
|
|
648
|
+
const now = Math.floor(Date.now() / 1000);
|
|
649
|
+
const isExpired = now > Number(claimData.timestamp) + 60 * 24 * 60 * 60;
|
|
650
|
+
return {
|
|
651
|
+
amount: Number(claimData.amount),
|
|
652
|
+
timestamp: Number(claimData.timestamp),
|
|
653
|
+
recipient: recipientKey.toBase58(),
|
|
654
|
+
isExpired,
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Get owner claimable amount
|
|
659
|
+
* @returns Owner claimable amount in USDC micro-units
|
|
660
|
+
*/
|
|
661
|
+
async getOwnerClaimable() {
|
|
662
|
+
const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
|
|
663
|
+
if (!accountInfo) {
|
|
664
|
+
throw new Error('Mailer state account not found');
|
|
665
|
+
}
|
|
666
|
+
const stateData = parseMailerState(accountInfo.data);
|
|
667
|
+
return Number(stateData.owner_claimable);
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Get delegation information for an address
|
|
671
|
+
* @param delegator Address to check delegation for, defaults to wallet address
|
|
672
|
+
* @returns Delegation info or null if no delegation
|
|
673
|
+
*/
|
|
674
|
+
async getDelegation(delegator) {
|
|
675
|
+
const delegatorKey = delegator || this.wallet.publicKey;
|
|
676
|
+
const [delegationPda] = PublicKey.findProgramAddressSync([Buffer.from('delegation'), delegatorKey.toBuffer()], this.programId);
|
|
677
|
+
const accountInfo = await this.connection.getAccountInfo(delegationPda);
|
|
678
|
+
if (!accountInfo) {
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
const delegationData = parseDelegation(accountInfo.data);
|
|
682
|
+
return {
|
|
683
|
+
delegator: delegatorKey.toBase58(),
|
|
684
|
+
delegate: delegationData.delegate
|
|
685
|
+
? delegationData.delegate.toBase58()
|
|
686
|
+
: null,
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Get the mailer state PDA address
|
|
691
|
+
* @returns PublicKey of the mailer state PDA
|
|
692
|
+
*/
|
|
693
|
+
getMailerStatePda() {
|
|
694
|
+
return this.mailerStatePda;
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Send a message to an email address (no wallet known)
|
|
698
|
+
* Charges only 10% owner fee since recipient wallet is unknown
|
|
699
|
+
* @param toEmail Email address of the recipient
|
|
700
|
+
* @param subject Message subject
|
|
701
|
+
* @param body Message body
|
|
702
|
+
* @param options Transaction confirm options
|
|
703
|
+
* @returns Transaction signature
|
|
704
|
+
*/
|
|
705
|
+
async sendToEmail(toEmail, subject, body, options, computeOptions) {
|
|
706
|
+
// Get associated token accounts
|
|
707
|
+
const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
708
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
709
|
+
// Check if accounts need to be created
|
|
710
|
+
const instructions = [];
|
|
711
|
+
// Check if mailer token account exists
|
|
712
|
+
const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
|
|
713
|
+
if (!mailerTokenInfo) {
|
|
714
|
+
instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
|
|
715
|
+
}
|
|
716
|
+
// Encode instruction data for SendToEmail
|
|
717
|
+
const instructionData = encodeSendToEmail(toEmail, subject, body);
|
|
718
|
+
// Create send instruction
|
|
719
|
+
instructions.push(new TransactionInstruction({
|
|
720
|
+
keys: [
|
|
721
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
722
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
723
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
724
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
725
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
726
|
+
],
|
|
727
|
+
programId: this.programId,
|
|
728
|
+
data: instructionData,
|
|
729
|
+
}));
|
|
730
|
+
const transaction = new Transaction().add(...instructions);
|
|
731
|
+
return this.sendTransaction(transaction, options, computeOptions);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Send a prepared message to an email address (no wallet known)
|
|
735
|
+
* Charges only 10% owner fee since recipient wallet is unknown
|
|
736
|
+
* @param toEmail Email address of the recipient
|
|
737
|
+
* @param mailId Pre-prepared message ID
|
|
738
|
+
* @param options Transaction confirm options
|
|
739
|
+
* @returns Transaction signature
|
|
740
|
+
*/
|
|
741
|
+
async sendPreparedToEmail(toEmail, mailId, options, computeOptions) {
|
|
742
|
+
// Get associated token accounts
|
|
743
|
+
const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
744
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
745
|
+
// Check if accounts need to be created
|
|
746
|
+
const instructions = [];
|
|
747
|
+
// Check if mailer token account exists
|
|
748
|
+
const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
|
|
749
|
+
if (!mailerTokenInfo) {
|
|
750
|
+
instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
|
|
751
|
+
}
|
|
752
|
+
// Encode instruction data for SendPreparedToEmail
|
|
753
|
+
const instructionData = encodeSendPreparedToEmail(toEmail, mailId);
|
|
754
|
+
// Create send instruction
|
|
755
|
+
instructions.push(new TransactionInstruction({
|
|
756
|
+
keys: [
|
|
757
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
758
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
759
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
760
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
761
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
762
|
+
],
|
|
763
|
+
programId: this.programId,
|
|
764
|
+
data: instructionData,
|
|
765
|
+
}));
|
|
766
|
+
const transaction = new Transaction().add(...instructions);
|
|
767
|
+
return this.sendTransaction(transaction, options, computeOptions);
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Send a prepared message using a mailId (to match EVM behavior)
|
|
771
|
+
* @param to Recipient's public key or address string
|
|
772
|
+
* @param mailId Pre-prepared message identifier
|
|
773
|
+
* @param revenueShareToReceiver If true, recipient gets 90% revenue share
|
|
774
|
+
* @param resolveSenderToName If true, resolve sender address to name
|
|
775
|
+
* @returns Transaction signature
|
|
776
|
+
*/
|
|
777
|
+
async sendPrepared(to, mailId, revenueShareToReceiver = false, resolveSenderToName = false, computeOptions) {
|
|
778
|
+
const recipientKey = typeof to === 'string' ? new PublicKey(to) : to;
|
|
779
|
+
const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
780
|
+
const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
781
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
782
|
+
const instructions = [];
|
|
783
|
+
const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
|
|
784
|
+
if (!mailerTokenInfo) {
|
|
785
|
+
instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
|
|
786
|
+
}
|
|
787
|
+
const sendInstruction = new TransactionInstruction({
|
|
788
|
+
keys: [
|
|
789
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
790
|
+
{ pubkey: recipientClaimPda, isSigner: false, isWritable: true },
|
|
791
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
792
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
793
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
794
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
795
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
796
|
+
],
|
|
797
|
+
programId: this.programId,
|
|
798
|
+
data: encodeSendPrepared(recipientKey, mailId, revenueShareToReceiver, resolveSenderToName),
|
|
799
|
+
});
|
|
800
|
+
instructions.push(sendInstruction);
|
|
801
|
+
const transaction = new Transaction().add(...instructions);
|
|
802
|
+
return this.sendTransaction(transaction, undefined, computeOptions);
|
|
803
|
+
}
|
|
804
|
+
async sendThroughWebhook(to, webhookId, revenueShareToReceiver = false, resolveSenderToName = false, computeOptions) {
|
|
805
|
+
const recipientKey = typeof to === 'string' ? new PublicKey(to) : to;
|
|
806
|
+
const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
807
|
+
const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
808
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
809
|
+
const instructions = [];
|
|
810
|
+
const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
|
|
811
|
+
if (!mailerTokenInfo) {
|
|
812
|
+
instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
|
|
813
|
+
}
|
|
814
|
+
const sendInstruction = new TransactionInstruction({
|
|
815
|
+
keys: [
|
|
816
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
817
|
+
{ pubkey: recipientClaimPda, isSigner: false, isWritable: true },
|
|
818
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
819
|
+
{ pubkey: senderTokenAccount, isSigner: false, isWritable: true },
|
|
820
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
821
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
822
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
823
|
+
],
|
|
824
|
+
programId: this.programId,
|
|
825
|
+
data: encodeSendThroughWebhook(recipientKey, webhookId, revenueShareToReceiver, resolveSenderToName),
|
|
826
|
+
});
|
|
827
|
+
instructions.push(sendInstruction);
|
|
828
|
+
const transaction = new Transaction().add(...instructions);
|
|
829
|
+
return this.sendTransaction(transaction, undefined, computeOptions);
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Pause the contract and distribute owner claimable funds (owner only)
|
|
833
|
+
* @param options Transaction confirm options
|
|
834
|
+
* @returns Transaction signature
|
|
835
|
+
*/
|
|
836
|
+
async pause(options, computeOptions) {
|
|
837
|
+
const ownerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
|
|
838
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
839
|
+
const instruction = new TransactionInstruction({
|
|
840
|
+
keys: [
|
|
841
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
842
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
843
|
+
{ pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
|
|
844
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
845
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
846
|
+
],
|
|
847
|
+
programId: this.programId,
|
|
848
|
+
data: encodeSimpleInstruction(InstructionType.Pause),
|
|
849
|
+
});
|
|
850
|
+
const transaction = new Transaction().add(instruction);
|
|
851
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Unpause the contract (owner only)
|
|
855
|
+
* @param options Transaction confirm options
|
|
856
|
+
* @returns Transaction signature
|
|
857
|
+
*/
|
|
858
|
+
async unpause(options, computeOptions) {
|
|
859
|
+
const instruction = new TransactionInstruction({
|
|
860
|
+
keys: [
|
|
861
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
862
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
863
|
+
],
|
|
864
|
+
programId: this.programId,
|
|
865
|
+
data: encodeSimpleInstruction(InstructionType.Unpause),
|
|
866
|
+
});
|
|
867
|
+
const transaction = new Transaction().add(instruction);
|
|
868
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Emergency unpause without fund distribution (owner only)
|
|
872
|
+
* @param options Transaction confirm options
|
|
873
|
+
* @returns Transaction signature
|
|
874
|
+
*/
|
|
875
|
+
async emergencyUnpause(options, computeOptions) {
|
|
876
|
+
const instruction = new TransactionInstruction({
|
|
877
|
+
keys: [
|
|
878
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
879
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
|
|
880
|
+
],
|
|
881
|
+
programId: this.programId,
|
|
882
|
+
data: encodeSimpleInstruction(InstructionType.EmergencyUnpause),
|
|
883
|
+
});
|
|
884
|
+
const transaction = new Transaction().add(instruction);
|
|
885
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Distribute claimable funds to a recipient when contract is paused
|
|
889
|
+
* @param recipient Recipient address to distribute funds for
|
|
890
|
+
* @param options Transaction confirm options
|
|
891
|
+
* @returns Transaction signature
|
|
892
|
+
*/
|
|
893
|
+
async distributeClaimableFunds(recipient, options, computeOptions) {
|
|
894
|
+
const recipientKey = typeof recipient === 'string' ? new PublicKey(recipient) : recipient;
|
|
895
|
+
const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
896
|
+
const recipientTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, recipientKey);
|
|
897
|
+
const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
|
|
898
|
+
// Encode the recipient parameter
|
|
899
|
+
const data = Buffer.alloc(1 + 32);
|
|
900
|
+
data.writeUInt8(InstructionType.DistributeClaimableFunds, 0);
|
|
901
|
+
recipientKey.toBuffer().copy(data, 1);
|
|
902
|
+
const instruction = new TransactionInstruction({
|
|
903
|
+
keys: [
|
|
904
|
+
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
905
|
+
{ pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
|
|
906
|
+
{ pubkey: recipientClaimPda, isSigner: false, isWritable: true },
|
|
907
|
+
{ pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
|
|
908
|
+
{ pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
|
|
909
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
910
|
+
],
|
|
911
|
+
programId: this.programId,
|
|
912
|
+
data,
|
|
913
|
+
});
|
|
914
|
+
const transaction = new Transaction().add(instruction);
|
|
915
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Get the current send fee
|
|
919
|
+
* @returns Send fee in USDC micro-units (6 decimals)
|
|
920
|
+
*/
|
|
921
|
+
async getSendFee() {
|
|
922
|
+
const fees = await this.getFees();
|
|
923
|
+
return BigInt(fees.sendFee);
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Check if contract is currently paused
|
|
927
|
+
* @returns True if contract is paused, false otherwise
|
|
928
|
+
*/
|
|
929
|
+
async isPaused() {
|
|
930
|
+
const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
|
|
931
|
+
if (!accountInfo) {
|
|
932
|
+
throw new Error('Mailer state account not found - program not initialized');
|
|
933
|
+
}
|
|
934
|
+
const stateData = parseMailerState(accountInfo.data);
|
|
935
|
+
// paused field is at offset: 32 + 32 + 8 + 8 + 8 = 88 bytes
|
|
936
|
+
return stateData.paused;
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Send and confirm a transaction
|
|
940
|
+
* @param transaction Transaction to send
|
|
941
|
+
* @param options Confirm options
|
|
942
|
+
* @returns Transaction signature
|
|
943
|
+
*/
|
|
944
|
+
async sendTransaction(transaction, options, computeOptions) {
|
|
945
|
+
// Optimize compute units if requested
|
|
946
|
+
const { transaction: optimizedTx, simulatedUnits } = await this.optimizeComputeUnits(transaction, computeOptions);
|
|
947
|
+
// Get recent blockhash
|
|
948
|
+
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
949
|
+
optimizedTx.recentBlockhash = blockhash;
|
|
950
|
+
optimizedTx.feePayer = this.wallet.publicKey;
|
|
951
|
+
// Sign transaction
|
|
952
|
+
const signedTx = await this.wallet.signTransaction(optimizedTx);
|
|
953
|
+
// Send and confirm
|
|
954
|
+
const signature = await this.connection.sendRawTransaction(signedTx.serialize());
|
|
955
|
+
await this.connection.confirmTransaction(signature, options?.commitment || 'confirmed');
|
|
956
|
+
return {
|
|
957
|
+
signature,
|
|
958
|
+
simulatedUnits,
|
|
959
|
+
computeUnitLimit: computeOptions?.computeUnitLimit,
|
|
960
|
+
computeUnitPrice: computeOptions?.computeUnitPrice,
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Create a simple wallet from a keypair for testing
|
|
965
|
+
* @param keypair Solana keypair
|
|
966
|
+
* @returns Wallet interface implementation
|
|
967
|
+
*/
|
|
968
|
+
static createWallet(keypair) {
|
|
969
|
+
return {
|
|
970
|
+
publicKey: keypair.publicKey,
|
|
971
|
+
async signTransaction(transaction) {
|
|
972
|
+
transaction.partialSign(keypair);
|
|
973
|
+
return transaction;
|
|
974
|
+
},
|
|
975
|
+
async signAllTransactions(transactions) {
|
|
976
|
+
return transactions.map((tx) => {
|
|
977
|
+
tx.partialSign(keypair);
|
|
978
|
+
return tx;
|
|
979
|
+
});
|
|
980
|
+
},
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
// Wallet interface is exported above
|
|
985
|
+
//# sourceMappingURL=mailer-client.js.map
|