@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,1236 @@
|
|
|
1
|
+
use borsh::BorshDeserialize;
|
|
2
|
+
use solana_program::{
|
|
3
|
+
instruction::{AccountMeta, Instruction},
|
|
4
|
+
program_pack::Pack,
|
|
5
|
+
pubkey::Pubkey,
|
|
6
|
+
system_program,
|
|
7
|
+
};
|
|
8
|
+
use solana_program_test::*;
|
|
9
|
+
use solana_sdk::{
|
|
10
|
+
signature::{Keypair, Signer},
|
|
11
|
+
transaction::Transaction,
|
|
12
|
+
};
|
|
13
|
+
use spl_token::{
|
|
14
|
+
instruction as spl_instruction,
|
|
15
|
+
state::{Account as TokenAccount, Mint},
|
|
16
|
+
};
|
|
17
|
+
use std::str::FromStr;
|
|
18
|
+
|
|
19
|
+
// Import our program
|
|
20
|
+
use mailer::{Delegation, MailerInstruction, MailerState, RecipientClaim};
|
|
21
|
+
|
|
22
|
+
// Program ID for tests
|
|
23
|
+
const PROGRAM_ID_STR: &str = "9FLkBDGpZBcR8LMsQ7MwwV6X9P4TDFgN3DeRh5qYyHJF";
|
|
24
|
+
|
|
25
|
+
fn program_id() -> Pubkey {
|
|
26
|
+
Pubkey::from_str(PROGRAM_ID_STR).unwrap()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// Test helper to create a test USDC mint
|
|
30
|
+
async fn create_usdc_mint(
|
|
31
|
+
banks_client: &mut BanksClient,
|
|
32
|
+
payer: &Keypair,
|
|
33
|
+
recent_blockhash: solana_program::hash::Hash,
|
|
34
|
+
) -> Pubkey {
|
|
35
|
+
let mint = Keypair::new();
|
|
36
|
+
let rent = banks_client.get_rent().await.unwrap();
|
|
37
|
+
let mint_rent = rent.minimum_balance(Mint::LEN);
|
|
38
|
+
|
|
39
|
+
let mut transaction = Transaction::new_with_payer(
|
|
40
|
+
&[
|
|
41
|
+
solana_sdk::system_instruction::create_account(
|
|
42
|
+
&payer.pubkey(),
|
|
43
|
+
&mint.pubkey(),
|
|
44
|
+
mint_rent,
|
|
45
|
+
Mint::LEN as u64,
|
|
46
|
+
&spl_token::id(),
|
|
47
|
+
),
|
|
48
|
+
spl_instruction::initialize_mint(
|
|
49
|
+
&spl_token::id(),
|
|
50
|
+
&mint.pubkey(),
|
|
51
|
+
&payer.pubkey(),
|
|
52
|
+
None,
|
|
53
|
+
6, // USDC has 6 decimals
|
|
54
|
+
)
|
|
55
|
+
.unwrap(),
|
|
56
|
+
],
|
|
57
|
+
Some(&payer.pubkey()),
|
|
58
|
+
);
|
|
59
|
+
transaction.sign(&[payer, &mint], recent_blockhash);
|
|
60
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
61
|
+
|
|
62
|
+
mint.pubkey()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Test helper to create a token account for a user
|
|
66
|
+
async fn create_token_account(
|
|
67
|
+
banks_client: &mut BanksClient,
|
|
68
|
+
payer: &Keypair,
|
|
69
|
+
recent_blockhash: solana_program::hash::Hash,
|
|
70
|
+
mint: &Pubkey,
|
|
71
|
+
owner: &Pubkey,
|
|
72
|
+
) -> Pubkey {
|
|
73
|
+
let account = Keypair::new();
|
|
74
|
+
let rent = banks_client.get_rent().await.unwrap();
|
|
75
|
+
let account_rent = rent.minimum_balance(TokenAccount::LEN);
|
|
76
|
+
|
|
77
|
+
let mut transaction = Transaction::new_with_payer(
|
|
78
|
+
&[
|
|
79
|
+
solana_sdk::system_instruction::create_account(
|
|
80
|
+
&payer.pubkey(),
|
|
81
|
+
&account.pubkey(),
|
|
82
|
+
account_rent,
|
|
83
|
+
TokenAccount::LEN as u64,
|
|
84
|
+
&spl_token::id(),
|
|
85
|
+
),
|
|
86
|
+
spl_instruction::initialize_account(&spl_token::id(), &account.pubkey(), mint, owner)
|
|
87
|
+
.unwrap(),
|
|
88
|
+
],
|
|
89
|
+
Some(&payer.pubkey()),
|
|
90
|
+
);
|
|
91
|
+
transaction.sign(&[payer, &account], recent_blockhash);
|
|
92
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
93
|
+
|
|
94
|
+
account.pubkey()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Test helper to mint tokens to an account
|
|
98
|
+
async fn mint_to(
|
|
99
|
+
banks_client: &mut BanksClient,
|
|
100
|
+
payer: &Keypair,
|
|
101
|
+
recent_blockhash: solana_program::hash::Hash,
|
|
102
|
+
mint: &Pubkey,
|
|
103
|
+
account: &Pubkey,
|
|
104
|
+
amount: u64,
|
|
105
|
+
) {
|
|
106
|
+
let mut transaction = Transaction::new_with_payer(
|
|
107
|
+
&[spl_instruction::mint_to(
|
|
108
|
+
&spl_token::id(),
|
|
109
|
+
mint,
|
|
110
|
+
account,
|
|
111
|
+
&payer.pubkey(),
|
|
112
|
+
&[],
|
|
113
|
+
amount,
|
|
114
|
+
)
|
|
115
|
+
.unwrap()],
|
|
116
|
+
Some(&payer.pubkey()),
|
|
117
|
+
);
|
|
118
|
+
transaction.sign(&[payer], recent_blockhash);
|
|
119
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// Test helper to get mailer state PDA
|
|
123
|
+
fn get_mailer_pda() -> (Pubkey, u8) {
|
|
124
|
+
Pubkey::find_program_address(&[b"mailer"], &program_id())
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/// Test helper to get recipient claim PDA
|
|
128
|
+
fn get_claim_pda(recipient: &Pubkey) -> (Pubkey, u8) {
|
|
129
|
+
Pubkey::find_program_address(&[b"claim", recipient.as_ref()], &program_id())
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/// Test helper to get delegation PDA
|
|
133
|
+
fn get_delegation_pda(delegator: &Pubkey) -> (Pubkey, u8) {
|
|
134
|
+
Pubkey::find_program_address(&[b"delegation", delegator.as_ref()], &program_id())
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#[tokio::test]
|
|
138
|
+
async fn test_initialize_program() {
|
|
139
|
+
let program_test = ProgramTest::new(
|
|
140
|
+
"mailer",
|
|
141
|
+
program_id(),
|
|
142
|
+
processor!(mailer::process_instruction),
|
|
143
|
+
);
|
|
144
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
145
|
+
|
|
146
|
+
// Create USDC mint
|
|
147
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
148
|
+
|
|
149
|
+
// Get mailer state PDA
|
|
150
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
151
|
+
|
|
152
|
+
// Initialize the program
|
|
153
|
+
let instruction_data = MailerInstruction::Initialize { usdc_mint };
|
|
154
|
+
let instruction = Instruction::new_with_borsh(
|
|
155
|
+
program_id(),
|
|
156
|
+
&instruction_data,
|
|
157
|
+
vec![
|
|
158
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
159
|
+
AccountMeta::new(mailer_pda, false),
|
|
160
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
161
|
+
],
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
|
165
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
166
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
167
|
+
|
|
168
|
+
// Verify the mailer state was initialized correctly
|
|
169
|
+
let account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
170
|
+
let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &account.data[8..]).unwrap();
|
|
171
|
+
|
|
172
|
+
assert_eq!(mailer_state.owner, payer.pubkey());
|
|
173
|
+
assert_eq!(mailer_state.usdc_mint, usdc_mint);
|
|
174
|
+
assert_eq!(mailer_state.send_fee, 100_000); // 0.1 USDC
|
|
175
|
+
assert_eq!(mailer_state.delegation_fee, 10_000_000); // 10 USDC
|
|
176
|
+
assert_eq!(mailer_state.owner_claimable, 0);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
#[tokio::test]
|
|
180
|
+
async fn test_send_priority_message() {
|
|
181
|
+
let program_test = ProgramTest::new(
|
|
182
|
+
"mailer",
|
|
183
|
+
program_id(),
|
|
184
|
+
processor!(mailer::process_instruction),
|
|
185
|
+
);
|
|
186
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
187
|
+
|
|
188
|
+
// Create USDC mint and accounts
|
|
189
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
190
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
191
|
+
|
|
192
|
+
// Initialize the program first
|
|
193
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
194
|
+
program_id(),
|
|
195
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
196
|
+
vec![
|
|
197
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
198
|
+
AccountMeta::new(mailer_pda, false),
|
|
199
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
200
|
+
],
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
204
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
205
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
206
|
+
|
|
207
|
+
// Create token accounts
|
|
208
|
+
let sender_usdc = create_token_account(
|
|
209
|
+
&mut banks_client,
|
|
210
|
+
&payer,
|
|
211
|
+
recent_blockhash,
|
|
212
|
+
&usdc_mint,
|
|
213
|
+
&payer.pubkey(),
|
|
214
|
+
)
|
|
215
|
+
.await;
|
|
216
|
+
let mailer_usdc = create_token_account(
|
|
217
|
+
&mut banks_client,
|
|
218
|
+
&payer,
|
|
219
|
+
recent_blockhash,
|
|
220
|
+
&usdc_mint,
|
|
221
|
+
&mailer_pda,
|
|
222
|
+
)
|
|
223
|
+
.await;
|
|
224
|
+
|
|
225
|
+
// Mint USDC to sender
|
|
226
|
+
mint_to(
|
|
227
|
+
&mut banks_client,
|
|
228
|
+
&payer,
|
|
229
|
+
recent_blockhash,
|
|
230
|
+
&usdc_mint,
|
|
231
|
+
&sender_usdc,
|
|
232
|
+
1_000_000,
|
|
233
|
+
)
|
|
234
|
+
.await; // 1 USDC
|
|
235
|
+
|
|
236
|
+
// Get recipient claim PDA
|
|
237
|
+
let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
|
|
238
|
+
|
|
239
|
+
// Send message with revenue sharing (priority mode)
|
|
240
|
+
let instruction_data = MailerInstruction::Send {
|
|
241
|
+
to: payer.pubkey(),
|
|
242
|
+
subject: "Test Subject".to_string(),
|
|
243
|
+
_body: "Test message body".to_string(),
|
|
244
|
+
revenue_share_to_receiver: true,
|
|
245
|
+
resolve_sender_to_name: false,
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
let instruction = Instruction::new_with_borsh(
|
|
249
|
+
program_id(),
|
|
250
|
+
&instruction_data,
|
|
251
|
+
vec![
|
|
252
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
253
|
+
AccountMeta::new(recipient_claim_pda, false),
|
|
254
|
+
AccountMeta::new(mailer_pda, false), // Must be writable for record_shares to update owner_claimable
|
|
255
|
+
AccountMeta::new(sender_usdc, false),
|
|
256
|
+
AccountMeta::new(mailer_usdc, false),
|
|
257
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
258
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
259
|
+
],
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
|
263
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
264
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
265
|
+
|
|
266
|
+
// Get the latest blockhash to ensure we're reading the most recent state
|
|
267
|
+
let _recent_blockhash = banks_client.get_latest_blockhash().await.unwrap();
|
|
268
|
+
|
|
269
|
+
// Verify recipient claim was created with correct amount
|
|
270
|
+
let claim_account = banks_client
|
|
271
|
+
.get_account(recipient_claim_pda)
|
|
272
|
+
.await
|
|
273
|
+
.unwrap()
|
|
274
|
+
.unwrap();
|
|
275
|
+
let recipient_claim: RecipientClaim =
|
|
276
|
+
BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
|
|
277
|
+
|
|
278
|
+
assert_eq!(recipient_claim.recipient, payer.pubkey());
|
|
279
|
+
assert_eq!(recipient_claim.amount, 90_000); // 90% of send_fee (100,000)
|
|
280
|
+
|
|
281
|
+
// Verify mailer state was updated with owner share
|
|
282
|
+
let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
283
|
+
let mailer_state: MailerState =
|
|
284
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
285
|
+
|
|
286
|
+
// Debug output
|
|
287
|
+
println!("Debug - Mailer state:");
|
|
288
|
+
println!(" owner: {}", mailer_state.owner);
|
|
289
|
+
println!(" usdc_mint: {}", mailer_state.usdc_mint);
|
|
290
|
+
println!(" send_fee: {}", mailer_state.send_fee);
|
|
291
|
+
println!(" delegation_fee: {}", mailer_state.delegation_fee);
|
|
292
|
+
println!(" owner_claimable: {}", mailer_state.owner_claimable);
|
|
293
|
+
println!(" bump: {}", mailer_state.bump);
|
|
294
|
+
|
|
295
|
+
assert_eq!(mailer_state.owner_claimable, 10_000); // 10% of send_fee
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
#[tokio::test]
|
|
299
|
+
async fn test_send_standard_message() {
|
|
300
|
+
let program_test = ProgramTest::new(
|
|
301
|
+
"mailer",
|
|
302
|
+
program_id(),
|
|
303
|
+
processor!(mailer::process_instruction),
|
|
304
|
+
);
|
|
305
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
306
|
+
|
|
307
|
+
// Setup similar to priority test
|
|
308
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
309
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
310
|
+
|
|
311
|
+
// Initialize the program
|
|
312
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
313
|
+
program_id(),
|
|
314
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
315
|
+
vec![
|
|
316
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
317
|
+
AccountMeta::new(mailer_pda, false),
|
|
318
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
319
|
+
],
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
323
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
324
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
325
|
+
|
|
326
|
+
// Create token accounts
|
|
327
|
+
let sender_usdc = create_token_account(
|
|
328
|
+
&mut banks_client,
|
|
329
|
+
&payer,
|
|
330
|
+
recent_blockhash,
|
|
331
|
+
&usdc_mint,
|
|
332
|
+
&payer.pubkey(),
|
|
333
|
+
)
|
|
334
|
+
.await;
|
|
335
|
+
let mailer_usdc = create_token_account(
|
|
336
|
+
&mut banks_client,
|
|
337
|
+
&payer,
|
|
338
|
+
recent_blockhash,
|
|
339
|
+
&usdc_mint,
|
|
340
|
+
&mailer_pda,
|
|
341
|
+
)
|
|
342
|
+
.await;
|
|
343
|
+
|
|
344
|
+
// Mint USDC to sender
|
|
345
|
+
mint_to(
|
|
346
|
+
&mut banks_client,
|
|
347
|
+
&payer,
|
|
348
|
+
recent_blockhash,
|
|
349
|
+
&usdc_mint,
|
|
350
|
+
&sender_usdc,
|
|
351
|
+
1_000_000,
|
|
352
|
+
)
|
|
353
|
+
.await;
|
|
354
|
+
|
|
355
|
+
// Get recipient claim PDA (needed even if not used for standard send)
|
|
356
|
+
let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
|
|
357
|
+
|
|
358
|
+
// Send standard message (no revenue sharing)
|
|
359
|
+
let instruction_data = MailerInstruction::Send {
|
|
360
|
+
to: payer.pubkey(),
|
|
361
|
+
subject: "Test Standard Subject".to_string(),
|
|
362
|
+
_body: "Test standard message body".to_string(),
|
|
363
|
+
revenue_share_to_receiver: false,
|
|
364
|
+
resolve_sender_to_name: false,
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
let instruction = Instruction::new_with_borsh(
|
|
368
|
+
program_id(),
|
|
369
|
+
&instruction_data,
|
|
370
|
+
vec![
|
|
371
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
372
|
+
AccountMeta::new_readonly(recipient_claim_pda, false), // Not used for standard send but required
|
|
373
|
+
AccountMeta::new(mailer_pda, false), // Needs to be writable to update owner_claimable
|
|
374
|
+
AccountMeta::new(sender_usdc, false),
|
|
375
|
+
AccountMeta::new(mailer_usdc, false),
|
|
376
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
377
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
378
|
+
],
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
|
382
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
383
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
384
|
+
|
|
385
|
+
// Verify only owner fee was charged (10% of send_fee = 10,000)
|
|
386
|
+
let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
387
|
+
let mailer_state: MailerState =
|
|
388
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
389
|
+
assert_eq!(mailer_state.owner_claimable, 10_000); // Only 10% fee
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
#[tokio::test]
|
|
393
|
+
async fn test_send_through_webhook_priority() {
|
|
394
|
+
let program_test = ProgramTest::new(
|
|
395
|
+
"mailer",
|
|
396
|
+
program_id(),
|
|
397
|
+
processor!(mailer::process_instruction),
|
|
398
|
+
);
|
|
399
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
400
|
+
|
|
401
|
+
// Setup similar to priority test
|
|
402
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
403
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
404
|
+
|
|
405
|
+
// Initialize the program
|
|
406
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
407
|
+
program_id(),
|
|
408
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
409
|
+
vec![
|
|
410
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
411
|
+
AccountMeta::new(mailer_pda, false),
|
|
412
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
413
|
+
],
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
417
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
418
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
419
|
+
|
|
420
|
+
// Create token accounts
|
|
421
|
+
let sender_usdc = create_token_account(
|
|
422
|
+
&mut banks_client,
|
|
423
|
+
&payer,
|
|
424
|
+
recent_blockhash,
|
|
425
|
+
&usdc_mint,
|
|
426
|
+
&payer.pubkey(),
|
|
427
|
+
)
|
|
428
|
+
.await;
|
|
429
|
+
let mailer_usdc = create_token_account(
|
|
430
|
+
&mut banks_client,
|
|
431
|
+
&payer,
|
|
432
|
+
recent_blockhash,
|
|
433
|
+
&usdc_mint,
|
|
434
|
+
&mailer_pda,
|
|
435
|
+
)
|
|
436
|
+
.await;
|
|
437
|
+
|
|
438
|
+
// Mint USDC to sender
|
|
439
|
+
mint_to(
|
|
440
|
+
&mut banks_client,
|
|
441
|
+
&payer,
|
|
442
|
+
recent_blockhash,
|
|
443
|
+
&usdc_mint,
|
|
444
|
+
&sender_usdc,
|
|
445
|
+
1_000_000,
|
|
446
|
+
)
|
|
447
|
+
.await; // 1 USDC
|
|
448
|
+
|
|
449
|
+
// Get recipient claim PDA
|
|
450
|
+
let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
|
|
451
|
+
|
|
452
|
+
// Send message through webhook with revenue sharing (priority mode)
|
|
453
|
+
let instruction_data = MailerInstruction::SendThroughWebhook {
|
|
454
|
+
to: payer.pubkey(),
|
|
455
|
+
webhook_id: "webhook-123".to_string(),
|
|
456
|
+
revenue_share_to_receiver: true,
|
|
457
|
+
resolve_sender_to_name: false,
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
let instruction = Instruction::new_with_borsh(
|
|
461
|
+
program_id(),
|
|
462
|
+
&instruction_data,
|
|
463
|
+
vec![
|
|
464
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
465
|
+
AccountMeta::new(recipient_claim_pda, false),
|
|
466
|
+
AccountMeta::new(mailer_pda, false), // Must be writable for record_shares to update owner_claimable
|
|
467
|
+
AccountMeta::new(sender_usdc, false),
|
|
468
|
+
AccountMeta::new(mailer_usdc, false),
|
|
469
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
470
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
471
|
+
],
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
|
475
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
476
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
477
|
+
|
|
478
|
+
// Verify recipient claim was created with correct amount
|
|
479
|
+
let claim_account = banks_client
|
|
480
|
+
.get_account(recipient_claim_pda)
|
|
481
|
+
.await
|
|
482
|
+
.unwrap()
|
|
483
|
+
.unwrap();
|
|
484
|
+
let recipient_claim: RecipientClaim =
|
|
485
|
+
BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
|
|
486
|
+
|
|
487
|
+
assert_eq!(recipient_claim.recipient, payer.pubkey());
|
|
488
|
+
assert_eq!(recipient_claim.amount, 90_000); // 90% of send_fee (100,000)
|
|
489
|
+
|
|
490
|
+
// Verify mailer state was updated with owner share
|
|
491
|
+
let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
492
|
+
let mailer_state: MailerState =
|
|
493
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
494
|
+
|
|
495
|
+
assert_eq!(mailer_state.owner_claimable, 10_000); // 10% of send_fee
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
#[tokio::test]
|
|
499
|
+
async fn test_send_through_webhook_standard() {
|
|
500
|
+
let program_test = ProgramTest::new(
|
|
501
|
+
"mailer",
|
|
502
|
+
program_id(),
|
|
503
|
+
processor!(mailer::process_instruction),
|
|
504
|
+
);
|
|
505
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
506
|
+
|
|
507
|
+
// Setup similar to standard test
|
|
508
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
509
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
510
|
+
|
|
511
|
+
// Initialize the program
|
|
512
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
513
|
+
program_id(),
|
|
514
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
515
|
+
vec![
|
|
516
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
517
|
+
AccountMeta::new(mailer_pda, false),
|
|
518
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
519
|
+
],
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
523
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
524
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
525
|
+
|
|
526
|
+
// Create token accounts
|
|
527
|
+
let sender_usdc = create_token_account(
|
|
528
|
+
&mut banks_client,
|
|
529
|
+
&payer,
|
|
530
|
+
recent_blockhash,
|
|
531
|
+
&usdc_mint,
|
|
532
|
+
&payer.pubkey(),
|
|
533
|
+
)
|
|
534
|
+
.await;
|
|
535
|
+
let mailer_usdc = create_token_account(
|
|
536
|
+
&mut banks_client,
|
|
537
|
+
&payer,
|
|
538
|
+
recent_blockhash,
|
|
539
|
+
&usdc_mint,
|
|
540
|
+
&mailer_pda,
|
|
541
|
+
)
|
|
542
|
+
.await;
|
|
543
|
+
|
|
544
|
+
// Mint USDC to sender
|
|
545
|
+
mint_to(
|
|
546
|
+
&mut banks_client,
|
|
547
|
+
&payer,
|
|
548
|
+
recent_blockhash,
|
|
549
|
+
&usdc_mint,
|
|
550
|
+
&sender_usdc,
|
|
551
|
+
1_000_000,
|
|
552
|
+
)
|
|
553
|
+
.await;
|
|
554
|
+
|
|
555
|
+
// Get recipient claim PDA (needed even if not used for standard send)
|
|
556
|
+
let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
|
|
557
|
+
|
|
558
|
+
// Send webhook message (standard mode - no revenue sharing)
|
|
559
|
+
let instruction_data = MailerInstruction::SendThroughWebhook {
|
|
560
|
+
to: payer.pubkey(),
|
|
561
|
+
webhook_id: "webhook-456".to_string(),
|
|
562
|
+
revenue_share_to_receiver: false,
|
|
563
|
+
resolve_sender_to_name: false,
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
let instruction = Instruction::new_with_borsh(
|
|
567
|
+
program_id(),
|
|
568
|
+
&instruction_data,
|
|
569
|
+
vec![
|
|
570
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
571
|
+
AccountMeta::new_readonly(recipient_claim_pda, false), // Not used for standard send but required
|
|
572
|
+
AccountMeta::new(mailer_pda, false), // Needs to be writable to update owner_claimable
|
|
573
|
+
AccountMeta::new(sender_usdc, false),
|
|
574
|
+
AccountMeta::new(mailer_usdc, false),
|
|
575
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
576
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
577
|
+
],
|
|
578
|
+
);
|
|
579
|
+
|
|
580
|
+
let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
|
|
581
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
582
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
583
|
+
|
|
584
|
+
// Verify only owner fee was charged (10% of send_fee = 10,000)
|
|
585
|
+
let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
586
|
+
let mailer_state: MailerState =
|
|
587
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
588
|
+
assert_eq!(mailer_state.owner_claimable, 10_000); // Only 10% fee
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
#[tokio::test]
|
|
592
|
+
async fn test_claim_recipient_share() {
|
|
593
|
+
let program_test = ProgramTest::new(
|
|
594
|
+
"mailer",
|
|
595
|
+
program_id(),
|
|
596
|
+
processor!(mailer::process_instruction),
|
|
597
|
+
);
|
|
598
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
599
|
+
|
|
600
|
+
// Setup and send priority message first (similar to previous test)
|
|
601
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
602
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
603
|
+
|
|
604
|
+
// Initialize
|
|
605
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
606
|
+
program_id(),
|
|
607
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
608
|
+
vec![
|
|
609
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
610
|
+
AccountMeta::new(mailer_pda, false),
|
|
611
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
612
|
+
],
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
616
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
617
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
618
|
+
|
|
619
|
+
// Create token accounts
|
|
620
|
+
let sender_usdc = create_token_account(
|
|
621
|
+
&mut banks_client,
|
|
622
|
+
&payer,
|
|
623
|
+
recent_blockhash,
|
|
624
|
+
&usdc_mint,
|
|
625
|
+
&payer.pubkey(),
|
|
626
|
+
)
|
|
627
|
+
.await;
|
|
628
|
+
let mailer_usdc = create_token_account(
|
|
629
|
+
&mut banks_client,
|
|
630
|
+
&payer,
|
|
631
|
+
recent_blockhash,
|
|
632
|
+
&usdc_mint,
|
|
633
|
+
&mailer_pda,
|
|
634
|
+
)
|
|
635
|
+
.await;
|
|
636
|
+
|
|
637
|
+
// Mint USDC
|
|
638
|
+
mint_to(
|
|
639
|
+
&mut banks_client,
|
|
640
|
+
&payer,
|
|
641
|
+
recent_blockhash,
|
|
642
|
+
&usdc_mint,
|
|
643
|
+
&sender_usdc,
|
|
644
|
+
1_000_000,
|
|
645
|
+
)
|
|
646
|
+
.await;
|
|
647
|
+
|
|
648
|
+
let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
|
|
649
|
+
|
|
650
|
+
// Send message with revenue sharing to create a claim
|
|
651
|
+
let send_instruction = Instruction::new_with_borsh(
|
|
652
|
+
program_id(),
|
|
653
|
+
&MailerInstruction::Send {
|
|
654
|
+
to: payer.pubkey(),
|
|
655
|
+
subject: "Test".to_string(),
|
|
656
|
+
_body: "Test".to_string(),
|
|
657
|
+
revenue_share_to_receiver: true,
|
|
658
|
+
resolve_sender_to_name: false,
|
|
659
|
+
},
|
|
660
|
+
vec![
|
|
661
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
662
|
+
AccountMeta::new(recipient_claim_pda, false),
|
|
663
|
+
AccountMeta::new_readonly(mailer_pda, false),
|
|
664
|
+
AccountMeta::new(sender_usdc, false),
|
|
665
|
+
AccountMeta::new(mailer_usdc, false),
|
|
666
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
667
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
668
|
+
],
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
let mut transaction = Transaction::new_with_payer(&[send_instruction], Some(&payer.pubkey()));
|
|
672
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
673
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
674
|
+
|
|
675
|
+
// Create recipient's own USDC account to receive the claim
|
|
676
|
+
let recipient_usdc = create_token_account(
|
|
677
|
+
&mut banks_client,
|
|
678
|
+
&payer,
|
|
679
|
+
recent_blockhash,
|
|
680
|
+
&usdc_mint,
|
|
681
|
+
&payer.pubkey(),
|
|
682
|
+
)
|
|
683
|
+
.await;
|
|
684
|
+
|
|
685
|
+
// Now claim the recipient share
|
|
686
|
+
let claim_instruction = Instruction::new_with_borsh(
|
|
687
|
+
program_id(),
|
|
688
|
+
&MailerInstruction::ClaimRecipientShare,
|
|
689
|
+
vec![
|
|
690
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
691
|
+
AccountMeta::new(recipient_claim_pda, false),
|
|
692
|
+
AccountMeta::new_readonly(mailer_pda, false),
|
|
693
|
+
AccountMeta::new(recipient_usdc, false),
|
|
694
|
+
AccountMeta::new(mailer_usdc, false),
|
|
695
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
696
|
+
],
|
|
697
|
+
);
|
|
698
|
+
|
|
699
|
+
let mut transaction = Transaction::new_with_payer(&[claim_instruction], Some(&payer.pubkey()));
|
|
700
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
701
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
702
|
+
|
|
703
|
+
// Verify the claim was processed
|
|
704
|
+
let claim_account = banks_client
|
|
705
|
+
.get_account(recipient_claim_pda)
|
|
706
|
+
.await
|
|
707
|
+
.unwrap()
|
|
708
|
+
.unwrap();
|
|
709
|
+
let recipient_claim: RecipientClaim =
|
|
710
|
+
BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
|
|
711
|
+
assert_eq!(recipient_claim.amount, 0); // Should be zero after claiming
|
|
712
|
+
|
|
713
|
+
// Verify tokens were transferred to recipient
|
|
714
|
+
let recipient_token_account = banks_client
|
|
715
|
+
.get_account(recipient_usdc)
|
|
716
|
+
.await
|
|
717
|
+
.unwrap()
|
|
718
|
+
.unwrap();
|
|
719
|
+
let token_account_data = TokenAccount::unpack(&recipient_token_account.data).unwrap();
|
|
720
|
+
assert_eq!(token_account_data.amount, 90_000); // 90% of 100,000
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
#[tokio::test]
|
|
724
|
+
async fn test_claim_owner_share() {
|
|
725
|
+
let program_test = ProgramTest::new(
|
|
726
|
+
"mailer",
|
|
727
|
+
program_id(),
|
|
728
|
+
processor!(mailer::process_instruction),
|
|
729
|
+
);
|
|
730
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
731
|
+
|
|
732
|
+
// Setup and send a message to accumulate owner fees
|
|
733
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
734
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
735
|
+
|
|
736
|
+
// Initialize
|
|
737
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
738
|
+
program_id(),
|
|
739
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
740
|
+
vec![
|
|
741
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
742
|
+
AccountMeta::new(mailer_pda, false),
|
|
743
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
744
|
+
],
|
|
745
|
+
);
|
|
746
|
+
|
|
747
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
748
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
749
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
750
|
+
|
|
751
|
+
// Setup token accounts and send standard message to accumulate owner fees
|
|
752
|
+
let sender_usdc = create_token_account(
|
|
753
|
+
&mut banks_client,
|
|
754
|
+
&payer,
|
|
755
|
+
recent_blockhash,
|
|
756
|
+
&usdc_mint,
|
|
757
|
+
&payer.pubkey(),
|
|
758
|
+
)
|
|
759
|
+
.await;
|
|
760
|
+
let mailer_usdc = create_token_account(
|
|
761
|
+
&mut banks_client,
|
|
762
|
+
&payer,
|
|
763
|
+
recent_blockhash,
|
|
764
|
+
&usdc_mint,
|
|
765
|
+
&mailer_pda,
|
|
766
|
+
)
|
|
767
|
+
.await;
|
|
768
|
+
let owner_usdc = create_token_account(
|
|
769
|
+
&mut banks_client,
|
|
770
|
+
&payer,
|
|
771
|
+
recent_blockhash,
|
|
772
|
+
&usdc_mint,
|
|
773
|
+
&payer.pubkey(),
|
|
774
|
+
)
|
|
775
|
+
.await;
|
|
776
|
+
|
|
777
|
+
mint_to(
|
|
778
|
+
&mut banks_client,
|
|
779
|
+
&payer,
|
|
780
|
+
recent_blockhash,
|
|
781
|
+
&usdc_mint,
|
|
782
|
+
&sender_usdc,
|
|
783
|
+
1_000_000,
|
|
784
|
+
)
|
|
785
|
+
.await;
|
|
786
|
+
|
|
787
|
+
let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
|
|
788
|
+
|
|
789
|
+
// Send standard message to accumulate owner fees (no revenue sharing)
|
|
790
|
+
let send_instruction = Instruction::new_with_borsh(
|
|
791
|
+
program_id(),
|
|
792
|
+
&MailerInstruction::Send {
|
|
793
|
+
to: payer.pubkey(),
|
|
794
|
+
subject: "Test".to_string(),
|
|
795
|
+
_body: "Test".to_string(),
|
|
796
|
+
revenue_share_to_receiver: false,
|
|
797
|
+
resolve_sender_to_name: false,
|
|
798
|
+
},
|
|
799
|
+
vec![
|
|
800
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
801
|
+
AccountMeta::new_readonly(recipient_claim_pda, false),
|
|
802
|
+
AccountMeta::new(mailer_pda, false),
|
|
803
|
+
AccountMeta::new(sender_usdc, false),
|
|
804
|
+
AccountMeta::new(mailer_usdc, false),
|
|
805
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
806
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
807
|
+
],
|
|
808
|
+
);
|
|
809
|
+
|
|
810
|
+
let mut transaction = Transaction::new_with_payer(&[send_instruction], Some(&payer.pubkey()));
|
|
811
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
812
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
813
|
+
|
|
814
|
+
// Now claim owner share
|
|
815
|
+
let claim_instruction = Instruction::new_with_borsh(
|
|
816
|
+
program_id(),
|
|
817
|
+
&MailerInstruction::ClaimOwnerShare,
|
|
818
|
+
vec![
|
|
819
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
820
|
+
AccountMeta::new(mailer_pda, false),
|
|
821
|
+
AccountMeta::new(owner_usdc, false),
|
|
822
|
+
AccountMeta::new(mailer_usdc, false),
|
|
823
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
824
|
+
],
|
|
825
|
+
);
|
|
826
|
+
|
|
827
|
+
let mut transaction = Transaction::new_with_payer(&[claim_instruction], Some(&payer.pubkey()));
|
|
828
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
829
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
830
|
+
|
|
831
|
+
// Verify owner claimable was reset
|
|
832
|
+
let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
833
|
+
let mailer_state: MailerState =
|
|
834
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
835
|
+
assert_eq!(mailer_state.owner_claimable, 0);
|
|
836
|
+
|
|
837
|
+
// Verify tokens were transferred to owner
|
|
838
|
+
let owner_token_account = banks_client.get_account(owner_usdc).await.unwrap().unwrap();
|
|
839
|
+
let token_account_data = TokenAccount::unpack(&owner_token_account.data).unwrap();
|
|
840
|
+
assert_eq!(token_account_data.amount, 10_000); // 10% of 100,000
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
#[tokio::test]
|
|
844
|
+
async fn test_set_fees() {
|
|
845
|
+
let program_test = ProgramTest::new(
|
|
846
|
+
"mailer",
|
|
847
|
+
program_id(),
|
|
848
|
+
processor!(mailer::process_instruction),
|
|
849
|
+
);
|
|
850
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
851
|
+
|
|
852
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
853
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
854
|
+
|
|
855
|
+
// Initialize
|
|
856
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
857
|
+
program_id(),
|
|
858
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
859
|
+
vec![
|
|
860
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
861
|
+
AccountMeta::new(mailer_pda, false),
|
|
862
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
863
|
+
],
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
867
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
868
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
869
|
+
|
|
870
|
+
// Test setting send fee
|
|
871
|
+
let set_fee_instruction = Instruction::new_with_borsh(
|
|
872
|
+
program_id(),
|
|
873
|
+
&MailerInstruction::SetFee { new_fee: 200_000 },
|
|
874
|
+
vec![
|
|
875
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
876
|
+
AccountMeta::new(mailer_pda, false),
|
|
877
|
+
],
|
|
878
|
+
);
|
|
879
|
+
|
|
880
|
+
let mut transaction =
|
|
881
|
+
Transaction::new_with_payer(&[set_fee_instruction], Some(&payer.pubkey()));
|
|
882
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
883
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
884
|
+
|
|
885
|
+
// Verify fee was updated
|
|
886
|
+
let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
887
|
+
let mailer_state: MailerState =
|
|
888
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
889
|
+
assert_eq!(mailer_state.send_fee, 200_000);
|
|
890
|
+
|
|
891
|
+
// Test setting delegation fee
|
|
892
|
+
let set_delegation_fee_instruction = Instruction::new_with_borsh(
|
|
893
|
+
program_id(),
|
|
894
|
+
&MailerInstruction::SetDelegationFee {
|
|
895
|
+
new_fee: 20_000_000,
|
|
896
|
+
},
|
|
897
|
+
vec![
|
|
898
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
899
|
+
AccountMeta::new(mailer_pda, false),
|
|
900
|
+
],
|
|
901
|
+
);
|
|
902
|
+
|
|
903
|
+
let mut transaction =
|
|
904
|
+
Transaction::new_with_payer(&[set_delegation_fee_instruction], Some(&payer.pubkey()));
|
|
905
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
906
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
907
|
+
|
|
908
|
+
// Verify delegation fee was updated
|
|
909
|
+
let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
|
|
910
|
+
let mailer_state: MailerState =
|
|
911
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
912
|
+
assert_eq!(mailer_state.delegation_fee, 20_000_000);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
#[tokio::test]
|
|
916
|
+
async fn test_delegation_functionality() {
|
|
917
|
+
let program_test = ProgramTest::new(
|
|
918
|
+
"mailer",
|
|
919
|
+
program_id(),
|
|
920
|
+
processor!(mailer::process_instruction),
|
|
921
|
+
);
|
|
922
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
923
|
+
|
|
924
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
925
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
926
|
+
|
|
927
|
+
// Initialize
|
|
928
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
929
|
+
program_id(),
|
|
930
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
931
|
+
vec![
|
|
932
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
933
|
+
AccountMeta::new(mailer_pda, false),
|
|
934
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
935
|
+
],
|
|
936
|
+
);
|
|
937
|
+
|
|
938
|
+
let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
|
|
939
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
940
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
941
|
+
|
|
942
|
+
// Setup token accounts
|
|
943
|
+
let delegator_usdc = create_token_account(
|
|
944
|
+
&mut banks_client,
|
|
945
|
+
&payer,
|
|
946
|
+
recent_blockhash,
|
|
947
|
+
&usdc_mint,
|
|
948
|
+
&payer.pubkey(),
|
|
949
|
+
)
|
|
950
|
+
.await;
|
|
951
|
+
let mailer_usdc = create_token_account(
|
|
952
|
+
&mut banks_client,
|
|
953
|
+
&payer,
|
|
954
|
+
recent_blockhash,
|
|
955
|
+
&usdc_mint,
|
|
956
|
+
&mailer_pda,
|
|
957
|
+
)
|
|
958
|
+
.await;
|
|
959
|
+
|
|
960
|
+
mint_to(
|
|
961
|
+
&mut banks_client,
|
|
962
|
+
&payer,
|
|
963
|
+
recent_blockhash,
|
|
964
|
+
&usdc_mint,
|
|
965
|
+
&delegator_usdc,
|
|
966
|
+
50_000_000,
|
|
967
|
+
)
|
|
968
|
+
.await; // 50 USDC
|
|
969
|
+
|
|
970
|
+
let delegate = Keypair::new();
|
|
971
|
+
let (delegation_pda, _) = get_delegation_pda(&payer.pubkey());
|
|
972
|
+
|
|
973
|
+
// Test delegation
|
|
974
|
+
let delegate_instruction = Instruction::new_with_borsh(
|
|
975
|
+
program_id(),
|
|
976
|
+
&MailerInstruction::DelegateTo {
|
|
977
|
+
delegate: Some(delegate.pubkey()),
|
|
978
|
+
},
|
|
979
|
+
vec![
|
|
980
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
981
|
+
AccountMeta::new(delegation_pda, false),
|
|
982
|
+
AccountMeta::new(mailer_pda, false),
|
|
983
|
+
AccountMeta::new(delegator_usdc, false),
|
|
984
|
+
AccountMeta::new(mailer_usdc, false),
|
|
985
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
986
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
987
|
+
],
|
|
988
|
+
);
|
|
989
|
+
|
|
990
|
+
let mut transaction =
|
|
991
|
+
Transaction::new_with_payer(&[delegate_instruction], Some(&payer.pubkey()));
|
|
992
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
993
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
994
|
+
|
|
995
|
+
// Verify delegation was created
|
|
996
|
+
let delegation_account = banks_client
|
|
997
|
+
.get_account(delegation_pda)
|
|
998
|
+
.await
|
|
999
|
+
.unwrap()
|
|
1000
|
+
.unwrap();
|
|
1001
|
+
let delegation: Delegation =
|
|
1002
|
+
BorshDeserialize::deserialize(&mut &delegation_account.data[8..]).unwrap();
|
|
1003
|
+
assert_eq!(delegation.delegator, payer.pubkey());
|
|
1004
|
+
assert_eq!(delegation.delegate, Some(delegate.pubkey()));
|
|
1005
|
+
|
|
1006
|
+
// Test rejection - disabled due to timeout issue
|
|
1007
|
+
// TODO: Fix rejection timeout issue
|
|
1008
|
+
/*
|
|
1009
|
+
let reject_instruction = Instruction::new_with_borsh(
|
|
1010
|
+
program_id(),
|
|
1011
|
+
&MailerInstruction::RejectDelegation,
|
|
1012
|
+
vec![
|
|
1013
|
+
AccountMeta::new(delegate.pubkey(), true),
|
|
1014
|
+
AccountMeta::new(delegation_pda, false),
|
|
1015
|
+
AccountMeta::new_readonly(mailer_pda, false),
|
|
1016
|
+
],
|
|
1017
|
+
);
|
|
1018
|
+
|
|
1019
|
+
let mut transaction = Transaction::new_with_payer(&[reject_instruction], Some(&delegate.pubkey()));
|
|
1020
|
+
transaction.sign(&[&delegate], recent_blockhash);
|
|
1021
|
+
banks_client.process_transaction(transaction).await.unwrap();
|
|
1022
|
+
|
|
1023
|
+
// Verify delegation was cleared
|
|
1024
|
+
let delegation_account = banks_client.get_account(delegation_pda).await.unwrap().unwrap();
|
|
1025
|
+
let delegation: Delegation = BorshDeserialize::deserialize(&mut &delegation_account.data[8..]).unwrap();
|
|
1026
|
+
assert_eq!(delegation.delegate, None);
|
|
1027
|
+
*/
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
#[tokio::test]
|
|
1031
|
+
async fn test_error_conditions() {
|
|
1032
|
+
let program_test = ProgramTest::new(
|
|
1033
|
+
"mailer",
|
|
1034
|
+
program_id(),
|
|
1035
|
+
processor!(mailer::process_instruction),
|
|
1036
|
+
);
|
|
1037
|
+
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
|
1038
|
+
|
|
1039
|
+
let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
|
|
1040
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
1041
|
+
|
|
1042
|
+
// Test claiming with no claimable amount (should fail)
|
|
1043
|
+
let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
|
|
1044
|
+
let recipient_usdc = create_token_account(
|
|
1045
|
+
&mut banks_client,
|
|
1046
|
+
&payer,
|
|
1047
|
+
recent_blockhash,
|
|
1048
|
+
&usdc_mint,
|
|
1049
|
+
&payer.pubkey(),
|
|
1050
|
+
)
|
|
1051
|
+
.await;
|
|
1052
|
+
let mailer_usdc = create_token_account(
|
|
1053
|
+
&mut banks_client,
|
|
1054
|
+
&payer,
|
|
1055
|
+
recent_blockhash,
|
|
1056
|
+
&usdc_mint,
|
|
1057
|
+
&mailer_pda,
|
|
1058
|
+
)
|
|
1059
|
+
.await;
|
|
1060
|
+
|
|
1061
|
+
let claim_instruction = Instruction::new_with_borsh(
|
|
1062
|
+
program_id(),
|
|
1063
|
+
&MailerInstruction::ClaimRecipientShare,
|
|
1064
|
+
vec![
|
|
1065
|
+
AccountMeta::new(payer.pubkey(), true),
|
|
1066
|
+
AccountMeta::new(recipient_claim_pda, false),
|
|
1067
|
+
AccountMeta::new_readonly(mailer_pda, false),
|
|
1068
|
+
AccountMeta::new(recipient_usdc, false),
|
|
1069
|
+
AccountMeta::new(mailer_usdc, false),
|
|
1070
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
1071
|
+
],
|
|
1072
|
+
);
|
|
1073
|
+
|
|
1074
|
+
let mut transaction = Transaction::new_with_payer(&[claim_instruction], Some(&payer.pubkey()));
|
|
1075
|
+
transaction.sign(&[&payer], recent_blockhash);
|
|
1076
|
+
|
|
1077
|
+
// This should fail because no claim exists
|
|
1078
|
+
let result = banks_client.process_transaction(transaction).await;
|
|
1079
|
+
assert!(result.is_err());
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
#[tokio::test]
|
|
1083
|
+
async fn test_claim_expired_shares_moves_funds_to_owner() {
|
|
1084
|
+
let program_test = ProgramTest::new(
|
|
1085
|
+
"mailer",
|
|
1086
|
+
program_id(),
|
|
1087
|
+
processor!(mailer::process_instruction),
|
|
1088
|
+
);
|
|
1089
|
+
let mut context = program_test.start_with_context().await;
|
|
1090
|
+
|
|
1091
|
+
let mut recent_blockhash = context.last_blockhash;
|
|
1092
|
+
|
|
1093
|
+
// Create USDC mint and initialize the program
|
|
1094
|
+
let usdc_mint =
|
|
1095
|
+
create_usdc_mint(&mut context.banks_client, &context.payer, recent_blockhash).await;
|
|
1096
|
+
recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
|
|
1097
|
+
|
|
1098
|
+
let (mailer_pda, _) = get_mailer_pda();
|
|
1099
|
+
let init_instruction = Instruction::new_with_borsh(
|
|
1100
|
+
program_id(),
|
|
1101
|
+
&MailerInstruction::Initialize { usdc_mint },
|
|
1102
|
+
vec![
|
|
1103
|
+
AccountMeta::new(context.payer.pubkey(), true),
|
|
1104
|
+
AccountMeta::new(mailer_pda, false),
|
|
1105
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
1106
|
+
],
|
|
1107
|
+
);
|
|
1108
|
+
|
|
1109
|
+
let mut transaction =
|
|
1110
|
+
Transaction::new_with_payer(&[init_instruction], Some(&context.payer.pubkey()));
|
|
1111
|
+
transaction.sign(&[&context.payer], recent_blockhash);
|
|
1112
|
+
context
|
|
1113
|
+
.banks_client
|
|
1114
|
+
.process_transaction(transaction)
|
|
1115
|
+
.await
|
|
1116
|
+
.unwrap();
|
|
1117
|
+
recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
|
|
1118
|
+
|
|
1119
|
+
// Prepare token accounts and fund the sender
|
|
1120
|
+
let sender_usdc = create_token_account(
|
|
1121
|
+
&mut context.banks_client,
|
|
1122
|
+
&context.payer,
|
|
1123
|
+
recent_blockhash,
|
|
1124
|
+
&usdc_mint,
|
|
1125
|
+
&context.payer.pubkey(),
|
|
1126
|
+
)
|
|
1127
|
+
.await;
|
|
1128
|
+
recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
|
|
1129
|
+
|
|
1130
|
+
let mailer_usdc = create_token_account(
|
|
1131
|
+
&mut context.banks_client,
|
|
1132
|
+
&context.payer,
|
|
1133
|
+
recent_blockhash,
|
|
1134
|
+
&usdc_mint,
|
|
1135
|
+
&mailer_pda,
|
|
1136
|
+
)
|
|
1137
|
+
.await;
|
|
1138
|
+
recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
|
|
1139
|
+
|
|
1140
|
+
mint_to(
|
|
1141
|
+
&mut context.banks_client,
|
|
1142
|
+
&context.payer,
|
|
1143
|
+
recent_blockhash,
|
|
1144
|
+
&usdc_mint,
|
|
1145
|
+
&sender_usdc,
|
|
1146
|
+
1_000_000,
|
|
1147
|
+
)
|
|
1148
|
+
.await; // 1 USDC to cover priority message
|
|
1149
|
+
recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
|
|
1150
|
+
|
|
1151
|
+
let (recipient_claim_pda, _) = get_claim_pda(&context.payer.pubkey());
|
|
1152
|
+
|
|
1153
|
+
// Send a priority message to create the claim record
|
|
1154
|
+
let send_instruction = Instruction::new_with_borsh(
|
|
1155
|
+
program_id(),
|
|
1156
|
+
&MailerInstruction::Send {
|
|
1157
|
+
to: context.payer.pubkey(),
|
|
1158
|
+
subject: "Expired claim".to_string(),
|
|
1159
|
+
_body: "Body".to_string(),
|
|
1160
|
+
revenue_share_to_receiver: true,
|
|
1161
|
+
resolve_sender_to_name: false,
|
|
1162
|
+
},
|
|
1163
|
+
vec![
|
|
1164
|
+
AccountMeta::new(context.payer.pubkey(), true),
|
|
1165
|
+
AccountMeta::new(recipient_claim_pda, false),
|
|
1166
|
+
AccountMeta::new(mailer_pda, false),
|
|
1167
|
+
AccountMeta::new(sender_usdc, false),
|
|
1168
|
+
AccountMeta::new(mailer_usdc, false),
|
|
1169
|
+
AccountMeta::new_readonly(spl_token::id(), false),
|
|
1170
|
+
AccountMeta::new_readonly(system_program::id(), false),
|
|
1171
|
+
],
|
|
1172
|
+
);
|
|
1173
|
+
|
|
1174
|
+
let mut transaction =
|
|
1175
|
+
Transaction::new_with_payer(&[send_instruction], Some(&context.payer.pubkey()));
|
|
1176
|
+
transaction.sign(&[&context.payer], recent_blockhash);
|
|
1177
|
+
context
|
|
1178
|
+
.banks_client
|
|
1179
|
+
.process_transaction(transaction)
|
|
1180
|
+
.await
|
|
1181
|
+
.unwrap();
|
|
1182
|
+
|
|
1183
|
+
// Warp forward so the claim expires (claim period is 60 days = 5,184,000 seconds)
|
|
1184
|
+
// Manually set the clock to a future timestamp beyond the claim period
|
|
1185
|
+
use solana_sdk::clock::Clock;
|
|
1186
|
+
let mut clock = context.banks_client.get_sysvar::<Clock>().await.unwrap();
|
|
1187
|
+
clock.unix_timestamp += 60 * 24 * 60 * 60 + 1; // 60 days + 1 second
|
|
1188
|
+
context.set_sysvar(&clock);
|
|
1189
|
+
|
|
1190
|
+
recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
|
|
1191
|
+
|
|
1192
|
+
// Owner reclaims expired shares
|
|
1193
|
+
let claim_expired_instruction = Instruction::new_with_borsh(
|
|
1194
|
+
program_id(),
|
|
1195
|
+
&MailerInstruction::ClaimExpiredShares {
|
|
1196
|
+
recipient: context.payer.pubkey(),
|
|
1197
|
+
},
|
|
1198
|
+
vec![
|
|
1199
|
+
AccountMeta::new(context.payer.pubkey(), true),
|
|
1200
|
+
AccountMeta::new(mailer_pda, false),
|
|
1201
|
+
AccountMeta::new(recipient_claim_pda, false),
|
|
1202
|
+
],
|
|
1203
|
+
);
|
|
1204
|
+
|
|
1205
|
+
let mut transaction =
|
|
1206
|
+
Transaction::new_with_payer(&[claim_expired_instruction], Some(&context.payer.pubkey()));
|
|
1207
|
+
transaction.sign(&[&context.payer], recent_blockhash);
|
|
1208
|
+
context
|
|
1209
|
+
.banks_client
|
|
1210
|
+
.process_transaction(transaction)
|
|
1211
|
+
.await
|
|
1212
|
+
.unwrap();
|
|
1213
|
+
|
|
1214
|
+
// Recipient claim should be cleared
|
|
1215
|
+
let claim_account = context
|
|
1216
|
+
.banks_client
|
|
1217
|
+
.get_account(recipient_claim_pda)
|
|
1218
|
+
.await
|
|
1219
|
+
.unwrap()
|
|
1220
|
+
.unwrap();
|
|
1221
|
+
let claim_state: RecipientClaim =
|
|
1222
|
+
BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
|
|
1223
|
+
assert_eq!(claim_state.amount, 0);
|
|
1224
|
+
assert_eq!(claim_state.timestamp, 0);
|
|
1225
|
+
|
|
1226
|
+
// Owner claimable should now include both original owner share and reclaimed amount (total 100,000)
|
|
1227
|
+
let mailer_account = context
|
|
1228
|
+
.banks_client
|
|
1229
|
+
.get_account(mailer_pda)
|
|
1230
|
+
.await
|
|
1231
|
+
.unwrap()
|
|
1232
|
+
.unwrap();
|
|
1233
|
+
let mailer_state: MailerState =
|
|
1234
|
+
BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
|
|
1235
|
+
assert_eq!(mailer_state.owner_claimable, 100_000);
|
|
1236
|
+
}
|