@opensea/sdk 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +70 -0
  3. package/lib/api/accounts.d.ts +27 -0
  4. package/lib/api/accounts.js +46 -0
  5. package/lib/api/accounts.js.map +1 -0
  6. package/lib/api/api.d.ts +489 -0
  7. package/lib/api/api.js +754 -0
  8. package/lib/api/api.js.map +1 -0
  9. package/lib/api/apiPaths.d.ts +46 -0
  10. package/lib/api/apiPaths.js +176 -0
  11. package/lib/api/apiPaths.js.map +1 -0
  12. package/lib/api/chains.d.ts +13 -0
  13. package/lib/api/chains.js +22 -0
  14. package/lib/api/chains.js.map +1 -0
  15. package/lib/api/collections.d.ts +34 -0
  16. package/lib/api/collections.js +80 -0
  17. package/lib/api/collections.js.map +1 -0
  18. package/lib/api/drops.d.ts +21 -0
  19. package/lib/api/drops.js +39 -0
  20. package/lib/api/drops.js.map +1 -0
  21. package/lib/api/events.d.ts +26 -0
  22. package/lib/api/events.js +43 -0
  23. package/lib/api/events.js.map +1 -0
  24. package/lib/api/fetcher.d.ts +24 -0
  25. package/lib/api/fetcher.js +3 -0
  26. package/lib/api/fetcher.js.map +1 -0
  27. package/lib/api/index.d.ts +2 -0
  28. package/lib/api/index.js +19 -0
  29. package/lib/api/index.js.map +1 -0
  30. package/lib/api/listings.d.ts +44 -0
  31. package/lib/api/listings.js +88 -0
  32. package/lib/api/listings.js.map +1 -0
  33. package/lib/api/nfts.d.ts +39 -0
  34. package/lib/api/nfts.js +79 -0
  35. package/lib/api/nfts.js.map +1 -0
  36. package/lib/api/offers.d.ts +54 -0
  37. package/lib/api/offers.js +124 -0
  38. package/lib/api/offers.js.map +1 -0
  39. package/lib/api/orders.d.ts +50 -0
  40. package/lib/api/orders.js +153 -0
  41. package/lib/api/orders.js.map +1 -0
  42. package/lib/api/search.d.ts +13 -0
  43. package/lib/api/search.js +22 -0
  44. package/lib/api/search.js.map +1 -0
  45. package/lib/api/tokens.d.ts +25 -0
  46. package/lib/api/tokens.js +43 -0
  47. package/lib/api/tokens.js.map +1 -0
  48. package/lib/api/types.d.ts +1113 -0
  49. package/lib/api/types.js +65 -0
  50. package/lib/api/types.js.map +1 -0
  51. package/lib/constants.d.ts +22 -0
  52. package/lib/constants.js +52 -0
  53. package/lib/constants.js.map +1 -0
  54. package/lib/index.d.ts +18 -0
  55. package/lib/index.js +24 -0
  56. package/lib/index.js.map +1 -0
  57. package/lib/orders/privateListings.d.ts +12 -0
  58. package/lib/orders/privateListings.js +130 -0
  59. package/lib/orders/privateListings.js.map +1 -0
  60. package/lib/orders/types.d.ts +160 -0
  61. package/lib/orders/types.js +10 -0
  62. package/lib/orders/types.js.map +1 -0
  63. package/lib/orders/utils.d.ts +89 -0
  64. package/lib/orders/utils.js +177 -0
  65. package/lib/orders/utils.js.map +1 -0
  66. package/lib/sdk/assets.d.ts +104 -0
  67. package/lib/sdk/assets.js +398 -0
  68. package/lib/sdk/assets.js.map +1 -0
  69. package/lib/sdk/cancellation.d.ts +97 -0
  70. package/lib/sdk/cancellation.js +235 -0
  71. package/lib/sdk/cancellation.js.map +1 -0
  72. package/lib/sdk/context.d.ts +28 -0
  73. package/lib/sdk/context.js +3 -0
  74. package/lib/sdk/context.js.map +1 -0
  75. package/lib/sdk/fulfillment.d.ts +153 -0
  76. package/lib/sdk/fulfillment.js +298 -0
  77. package/lib/sdk/fulfillment.js.map +1 -0
  78. package/lib/sdk/orders.d.ts +253 -0
  79. package/lib/sdk/orders.js +679 -0
  80. package/lib/sdk/orders.js.map +1 -0
  81. package/lib/sdk/tokens.d.ts +31 -0
  82. package/lib/sdk/tokens.js +65 -0
  83. package/lib/sdk/tokens.js.map +1 -0
  84. package/lib/sdk.d.ts +560 -0
  85. package/lib/sdk.js +693 -0
  86. package/lib/sdk.js.map +1 -0
  87. package/lib/src/api/accounts.d.ts +18 -0
  88. package/lib/src/api/accounts.js +30 -0
  89. package/lib/src/api/accounts.js.map +1 -0
  90. package/lib/src/api/api.d.ts +429 -0
  91. package/lib/src/api/api.js +652 -0
  92. package/lib/src/api/api.js.map +1 -0
  93. package/lib/src/api/apiPaths.d.ts +37 -0
  94. package/lib/src/api/apiPaths.js +140 -0
  95. package/lib/src/api/apiPaths.js.map +1 -0
  96. package/lib/src/api/collections.d.ts +26 -0
  97. package/lib/src/api/collections.js +57 -0
  98. package/lib/src/api/collections.js.map +1 -0
  99. package/lib/src/api/events.d.ts +26 -0
  100. package/lib/src/api/events.js +42 -0
  101. package/lib/src/api/events.js.map +1 -0
  102. package/lib/src/api/fetcher.d.ts +24 -0
  103. package/lib/src/api/fetcher.js +3 -0
  104. package/lib/src/api/fetcher.js.map +1 -0
  105. package/lib/src/api/index.d.ts +2 -0
  106. package/lib/src/api/index.js +19 -0
  107. package/lib/src/api/index.js.map +1 -0
  108. package/lib/src/api/listings.d.ts +44 -0
  109. package/lib/src/api/listings.js +86 -0
  110. package/lib/src/api/listings.js.map +1 -0
  111. package/lib/src/api/nfts.d.ts +35 -0
  112. package/lib/src/api/nfts.js +66 -0
  113. package/lib/src/api/nfts.js.map +1 -0
  114. package/lib/src/api/offers.d.ts +54 -0
  115. package/lib/src/api/offers.js +122 -0
  116. package/lib/src/api/offers.js.map +1 -0
  117. package/lib/src/api/orders.d.ts +50 -0
  118. package/lib/src/api/orders.js +151 -0
  119. package/lib/src/api/orders.js.map +1 -0
  120. package/lib/src/api/search.d.ts +13 -0
  121. package/lib/src/api/search.js +21 -0
  122. package/lib/src/api/search.js.map +1 -0
  123. package/lib/src/api/tokens.d.ts +25 -0
  124. package/lib/src/api/tokens.js +42 -0
  125. package/lib/src/api/tokens.js.map +1 -0
  126. package/lib/src/api/types.d.ts +840 -0
  127. package/lib/src/api/types.js +65 -0
  128. package/lib/src/api/types.js.map +1 -0
  129. package/lib/src/constants.d.ts +22 -0
  130. package/lib/src/constants.js +52 -0
  131. package/lib/src/constants.js.map +1 -0
  132. package/lib/src/index.d.ts +18 -0
  133. package/lib/src/index.js +24 -0
  134. package/lib/src/index.js.map +1 -0
  135. package/lib/src/orders/privateListings.d.ts +12 -0
  136. package/lib/src/orders/privateListings.js +130 -0
  137. package/lib/src/orders/privateListings.js.map +1 -0
  138. package/lib/src/orders/types.d.ts +160 -0
  139. package/lib/src/orders/types.js +10 -0
  140. package/lib/src/orders/types.js.map +1 -0
  141. package/lib/src/orders/utils.d.ts +89 -0
  142. package/lib/src/orders/utils.js +177 -0
  143. package/lib/src/orders/utils.js.map +1 -0
  144. package/lib/src/sdk/assets.d.ts +104 -0
  145. package/lib/src/sdk/assets.js +397 -0
  146. package/lib/src/sdk/assets.js.map +1 -0
  147. package/lib/src/sdk/cancellation.d.ts +97 -0
  148. package/lib/src/sdk/cancellation.js +234 -0
  149. package/lib/src/sdk/cancellation.js.map +1 -0
  150. package/lib/src/sdk/context.d.ts +28 -0
  151. package/lib/src/sdk/context.js +3 -0
  152. package/lib/src/sdk/context.js.map +1 -0
  153. package/lib/src/sdk/fulfillment.d.ts +153 -0
  154. package/lib/src/sdk/fulfillment.js +296 -0
  155. package/lib/src/sdk/fulfillment.js.map +1 -0
  156. package/lib/src/sdk/orders.d.ts +253 -0
  157. package/lib/src/sdk/orders.js +677 -0
  158. package/lib/src/sdk/orders.js.map +1 -0
  159. package/lib/src/sdk/tokens.d.ts +31 -0
  160. package/lib/src/sdk/tokens.js +64 -0
  161. package/lib/src/sdk/tokens.js.map +1 -0
  162. package/lib/src/sdk.d.ts +560 -0
  163. package/lib/src/sdk.js +675 -0
  164. package/lib/src/sdk.js.map +1 -0
  165. package/lib/src/typechain/contracts/ERC1155.d.ts +236 -0
  166. package/lib/src/typechain/contracts/ERC1155.js +3 -0
  167. package/lib/src/typechain/contracts/ERC1155.js.map +1 -0
  168. package/lib/src/typechain/contracts/ERC20.d.ts +141 -0
  169. package/lib/src/typechain/contracts/ERC20.js +3 -0
  170. package/lib/src/typechain/contracts/ERC20.js.map +1 -0
  171. package/lib/src/typechain/contracts/ERC721.d.ts +213 -0
  172. package/lib/src/typechain/contracts/ERC721.js +3 -0
  173. package/lib/src/typechain/contracts/ERC721.js.map +1 -0
  174. package/lib/src/typechain/contracts/Multicall3.d.ts +57 -0
  175. package/lib/src/typechain/contracts/Multicall3.js +3 -0
  176. package/lib/src/typechain/contracts/Multicall3.js.map +1 -0
  177. package/lib/src/typechain/contracts/TransferHelper.d.ts +55 -0
  178. package/lib/src/typechain/contracts/TransferHelper.js +3 -0
  179. package/lib/src/typechain/contracts/TransferHelper.js.map +1 -0
  180. package/lib/src/typechain/contracts/common.d.ts +50 -0
  181. package/lib/src/typechain/contracts/common.js +3 -0
  182. package/lib/src/typechain/contracts/common.js.map +1 -0
  183. package/lib/src/typechain/contracts/factories/ERC1155__factory.d.ts +250 -0
  184. package/lib/src/typechain/contracts/factories/ERC1155__factory.js +332 -0
  185. package/lib/src/typechain/contracts/factories/ERC1155__factory.js.map +1 -0
  186. package/lib/src/typechain/contracts/factories/ERC20__factory.d.ts +174 -0
  187. package/lib/src/typechain/contracts/factories/ERC20__factory.js +240 -0
  188. package/lib/src/typechain/contracts/factories/ERC20__factory.js.map +1 -0
  189. package/lib/src/typechain/contracts/factories/ERC721__factory.d.ts +268 -0
  190. package/lib/src/typechain/contracts/factories/ERC721__factory.js +351 -0
  191. package/lib/src/typechain/contracts/factories/ERC721__factory.js.map +1 -0
  192. package/lib/src/typechain/contracts/factories/Multicall3__factory.d.ts +43 -0
  193. package/lib/src/typechain/contracts/factories/Multicall3__factory.js +68 -0
  194. package/lib/src/typechain/contracts/factories/Multicall3__factory.js.map +1 -0
  195. package/lib/src/typechain/contracts/factories/TransferHelper__factory.d.ts +46 -0
  196. package/lib/src/typechain/contracts/factories/TransferHelper__factory.js +71 -0
  197. package/lib/src/typechain/contracts/factories/TransferHelper__factory.js.map +1 -0
  198. package/lib/src/typechain/contracts/factories/index.d.ts +5 -0
  199. package/lib/src/typechain/contracts/factories/index.js +17 -0
  200. package/lib/src/typechain/contracts/factories/index.js.map +1 -0
  201. package/lib/src/typechain/contracts/index.d.ts +11 -0
  202. package/lib/src/typechain/contracts/index.js +48 -0
  203. package/lib/src/typechain/contracts/index.js.map +1 -0
  204. package/lib/src/types.d.ts +387 -0
  205. package/lib/src/types.js +127 -0
  206. package/lib/src/types.js.map +1 -0
  207. package/lib/src/utils/chain.d.ts +60 -0
  208. package/lib/src/utils/chain.js +248 -0
  209. package/lib/src/utils/chain.js.map +1 -0
  210. package/lib/src/utils/converters.d.ts +37 -0
  211. package/lib/src/utils/converters.js +137 -0
  212. package/lib/src/utils/converters.js.map +1 -0
  213. package/lib/src/utils/dateHelper.d.ts +38 -0
  214. package/lib/src/utils/dateHelper.js +52 -0
  215. package/lib/src/utils/dateHelper.js.map +1 -0
  216. package/lib/src/utils/fees.d.ts +13 -0
  217. package/lib/src/utils/fees.js +29 -0
  218. package/lib/src/utils/fees.js.map +1 -0
  219. package/lib/src/utils/index.d.ts +2 -0
  220. package/lib/src/utils/index.js +19 -0
  221. package/lib/src/utils/index.js.map +1 -0
  222. package/lib/src/utils/protocol.d.ts +75 -0
  223. package/lib/src/utils/protocol.js +161 -0
  224. package/lib/src/utils/protocol.js.map +1 -0
  225. package/lib/src/utils/rateLimit.d.ts +34 -0
  226. package/lib/src/utils/rateLimit.js +97 -0
  227. package/lib/src/utils/rateLimit.js.map +1 -0
  228. package/lib/src/utils/stringHelper.d.ts +18 -0
  229. package/lib/src/utils/stringHelper.js +24 -0
  230. package/lib/src/utils/stringHelper.js.map +1 -0
  231. package/lib/src/utils/utils.d.ts +18 -0
  232. package/lib/src/utils/utils.js +45 -0
  233. package/lib/src/utils/utils.js.map +1 -0
  234. package/lib/typechain/contracts/ERC1155.d.ts +236 -0
  235. package/lib/typechain/contracts/ERC1155.js +3 -0
  236. package/lib/typechain/contracts/ERC1155.js.map +1 -0
  237. package/lib/typechain/contracts/ERC20.d.ts +141 -0
  238. package/lib/typechain/contracts/ERC20.js +3 -0
  239. package/lib/typechain/contracts/ERC20.js.map +1 -0
  240. package/lib/typechain/contracts/ERC721.d.ts +213 -0
  241. package/lib/typechain/contracts/ERC721.js +3 -0
  242. package/lib/typechain/contracts/ERC721.js.map +1 -0
  243. package/lib/typechain/contracts/Multicall3.d.ts +57 -0
  244. package/lib/typechain/contracts/Multicall3.js +3 -0
  245. package/lib/typechain/contracts/Multicall3.js.map +1 -0
  246. package/lib/typechain/contracts/TransferHelper.d.ts +55 -0
  247. package/lib/typechain/contracts/TransferHelper.js +3 -0
  248. package/lib/typechain/contracts/TransferHelper.js.map +1 -0
  249. package/lib/typechain/contracts/common.d.ts +50 -0
  250. package/lib/typechain/contracts/common.js +3 -0
  251. package/lib/typechain/contracts/common.js.map +1 -0
  252. package/lib/typechain/contracts/factories/ERC1155__factory.d.ts +250 -0
  253. package/lib/typechain/contracts/factories/ERC1155__factory.js +332 -0
  254. package/lib/typechain/contracts/factories/ERC1155__factory.js.map +1 -0
  255. package/lib/typechain/contracts/factories/ERC20__factory.d.ts +174 -0
  256. package/lib/typechain/contracts/factories/ERC20__factory.js +240 -0
  257. package/lib/typechain/contracts/factories/ERC20__factory.js.map +1 -0
  258. package/lib/typechain/contracts/factories/ERC721__factory.d.ts +268 -0
  259. package/lib/typechain/contracts/factories/ERC721__factory.js +351 -0
  260. package/lib/typechain/contracts/factories/ERC721__factory.js.map +1 -0
  261. package/lib/typechain/contracts/factories/Multicall3__factory.d.ts +43 -0
  262. package/lib/typechain/contracts/factories/Multicall3__factory.js +68 -0
  263. package/lib/typechain/contracts/factories/Multicall3__factory.js.map +1 -0
  264. package/lib/typechain/contracts/factories/TransferHelper__factory.d.ts +46 -0
  265. package/lib/typechain/contracts/factories/TransferHelper__factory.js +71 -0
  266. package/lib/typechain/contracts/factories/TransferHelper__factory.js.map +1 -0
  267. package/lib/typechain/contracts/factories/index.d.ts +5 -0
  268. package/lib/typechain/contracts/factories/index.js +17 -0
  269. package/lib/typechain/contracts/factories/index.js.map +1 -0
  270. package/lib/typechain/contracts/index.d.ts +11 -0
  271. package/lib/typechain/contracts/index.js +48 -0
  272. package/lib/typechain/contracts/index.js.map +1 -0
  273. package/lib/types.d.ts +389 -0
  274. package/lib/types.js +129 -0
  275. package/lib/types.js.map +1 -0
  276. package/lib/utils/chain.d.ts +64 -0
  277. package/lib/utils/chain.js +211 -0
  278. package/lib/utils/chain.js.map +1 -0
  279. package/lib/utils/chainIds.generated.d.ts +7 -0
  280. package/lib/utils/chainIds.generated.js +37 -0
  281. package/lib/utils/chainIds.generated.js.map +1 -0
  282. package/lib/utils/converters.d.ts +37 -0
  283. package/lib/utils/converters.js +137 -0
  284. package/lib/utils/converters.js.map +1 -0
  285. package/lib/utils/dateHelper.d.ts +38 -0
  286. package/lib/utils/dateHelper.js +52 -0
  287. package/lib/utils/dateHelper.js.map +1 -0
  288. package/lib/utils/fees.d.ts +13 -0
  289. package/lib/utils/fees.js +29 -0
  290. package/lib/utils/fees.js.map +1 -0
  291. package/lib/utils/index.d.ts +2 -0
  292. package/lib/utils/index.js +19 -0
  293. package/lib/utils/index.js.map +1 -0
  294. package/lib/utils/protocol.d.ts +75 -0
  295. package/lib/utils/protocol.js +161 -0
  296. package/lib/utils/protocol.js.map +1 -0
  297. package/lib/utils/rateLimit.d.ts +34 -0
  298. package/lib/utils/rateLimit.js +97 -0
  299. package/lib/utils/rateLimit.js.map +1 -0
  300. package/lib/utils/stringHelper.d.ts +18 -0
  301. package/lib/utils/stringHelper.js +24 -0
  302. package/lib/utils/stringHelper.js.map +1 -0
  303. package/lib/utils/utils.d.ts +18 -0
  304. package/lib/utils/utils.js +45 -0
  305. package/lib/utils/utils.js.map +1 -0
  306. package/package.json +72 -0
  307. package/src/abi/ERC1155.json +314 -0
  308. package/src/abi/ERC20.json +222 -0
  309. package/src/abi/ERC721.json +333 -0
  310. package/src/abi/Multicall3.json +50 -0
  311. package/src/abi/TransferHelper.json +53 -0
  312. package/src/api/accounts.ts +69 -0
  313. package/src/api/api.ts +1152 -0
  314. package/src/api/apiPaths.ts +208 -0
  315. package/src/api/chains.ts +18 -0
  316. package/src/api/collections.ts +120 -0
  317. package/src/api/drops.ts +49 -0
  318. package/src/api/events.ts +71 -0
  319. package/src/api/fetcher.ts +31 -0
  320. package/src/api/index.ts +2 -0
  321. package/src/api/listings.ts +126 -0
  322. package/src/api/nfts.ts +144 -0
  323. package/src/api/offers.ts +242 -0
  324. package/src/api/orders.ts +283 -0
  325. package/src/api/search.ts +21 -0
  326. package/src/api/tokens.ts +67 -0
  327. package/src/api/types.ts +1210 -0
  328. package/src/constants.ts +90 -0
  329. package/src/index.ts +22 -0
  330. package/src/orders/privateListings.ts +173 -0
  331. package/src/orders/types.ts +191 -0
  332. package/src/orders/utils.ts +253 -0
  333. package/src/sdk/assets.ts +591 -0
  334. package/src/sdk/cancellation.ts +346 -0
  335. package/src/sdk/context.ts +33 -0
  336. package/src/sdk/fulfillment.ts +478 -0
  337. package/src/sdk/orders.ts +1149 -0
  338. package/src/sdk/tokens.ts +95 -0
  339. package/src/sdk.ts +1051 -0
  340. package/src/typechain/contracts/ERC1155.ts +440 -0
  341. package/src/typechain/contracts/ERC20.ts +286 -0
  342. package/src/typechain/contracts/ERC721.ts +412 -0
  343. package/src/typechain/contracts/Multicall3.ts +117 -0
  344. package/src/typechain/contracts/TransferHelper.ts +122 -0
  345. package/src/typechain/contracts/common.ts +131 -0
  346. package/src/typechain/contracts/factories/ERC1155__factory.ts +331 -0
  347. package/src/typechain/contracts/factories/ERC20__factory.ts +239 -0
  348. package/src/typechain/contracts/factories/ERC721__factory.ts +350 -0
  349. package/src/typechain/contracts/factories/Multicall3__factory.ts +67 -0
  350. package/src/typechain/contracts/factories/TransferHelper__factory.ts +76 -0
  351. package/src/typechain/contracts/factories/index.ts +8 -0
  352. package/src/typechain/contracts/index.ts +14 -0
  353. package/src/types.ts +413 -0
  354. package/src/utils/chain.ts +224 -0
  355. package/src/utils/chainIds.generated.ts +34 -0
  356. package/src/utils/converters.ts +145 -0
  357. package/src/utils/dateHelper.ts +48 -0
  358. package/src/utils/fees.ts +31 -0
  359. package/src/utils/index.ts +2 -0
  360. package/src/utils/protocol.ts +185 -0
  361. package/src/utils/rateLimit.ts +147 -0
  362. package/src/utils/stringHelper.ts +25 -0
  363. package/src/utils/utils.ts +36 -0
@@ -0,0 +1,591 @@
1
+ import {
2
+ type BigNumberish,
3
+ Contract,
4
+ type ContractTransactionResponse,
5
+ ethers,
6
+ type Overrides,
7
+ type Signer,
8
+ } from "ethers"
9
+ import { MULTICALL3_ADDRESS, TRANSFER_HELPER_ADDRESS } from "../constants"
10
+ import {
11
+ ERC20__factory,
12
+ ERC721__factory,
13
+ ERC1155__factory,
14
+ } from "../typechain/contracts"
15
+ import { type AssetWithTokenStandard, EventType, TokenStandard } from "../types"
16
+ import { getDefaultConduit } from "../utils/utils"
17
+ import type { SDKContext } from "./context"
18
+
19
+ /**
20
+ * Asset transfer and approval operations
21
+ */
22
+ export class AssetsManager {
23
+ constructor(private context: SDKContext) {}
24
+
25
+ /**
26
+ * Get an account's balance of any Asset. This asset can be an ERC20, ERC1155, or ERC721.
27
+ * @param options
28
+ * @param options.accountAddress Account address to check
29
+ * @param options.asset The Asset to check balance for. tokenStandard must be set.
30
+ * @returns The balance of the asset for the account.
31
+ *
32
+ * @throws Error if the token standard does not support balanceOf.
33
+ */
34
+ async getBalance({
35
+ accountAddress,
36
+ asset,
37
+ }: {
38
+ accountAddress: string
39
+ asset: AssetWithTokenStandard
40
+ }): Promise<bigint> {
41
+ switch (asset.tokenStandard) {
42
+ case TokenStandard.ERC20: {
43
+ const contract = ERC20__factory.connect(
44
+ asset.tokenAddress,
45
+ this.context.provider,
46
+ )
47
+ return await contract.balanceOf.staticCall(accountAddress)
48
+ }
49
+ case TokenStandard.ERC1155: {
50
+ if (asset.tokenId === undefined || asset.tokenId === null) {
51
+ throw new Error("Missing ERC1155 tokenId for getBalance")
52
+ }
53
+ const contract = ERC1155__factory.connect(
54
+ asset.tokenAddress,
55
+ this.context.provider,
56
+ )
57
+ return await contract.balanceOf.staticCall(
58
+ accountAddress,
59
+ asset.tokenId,
60
+ )
61
+ }
62
+ case TokenStandard.ERC721: {
63
+ if (asset.tokenId === undefined || asset.tokenId === null) {
64
+ throw new Error("Missing ERC721 tokenId for getBalance")
65
+ }
66
+ const contract = ERC721__factory.connect(
67
+ asset.tokenAddress,
68
+ this.context.provider,
69
+ )
70
+ try {
71
+ const owner = await contract.ownerOf.staticCall(asset.tokenId)
72
+ return BigInt(owner.toLowerCase() === accountAddress.toLowerCase())
73
+ } catch (error: any) {
74
+ this.context.logger(
75
+ `Failed to get ownerOf ERC721: ${error.message ?? error}`,
76
+ )
77
+ return 0n
78
+ }
79
+ }
80
+ default:
81
+ throw new Error("Unsupported token standard for getBalance")
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Transfer an asset. This asset can be an ERC20, ERC1155, or ERC721.
87
+ * @param options
88
+ * @param options.asset The Asset to transfer. tokenStandard must be set.
89
+ * @param options.amount Amount of asset to transfer. Not used for ERC721.
90
+ * @param options.fromAddress The address to transfer from
91
+ * @param options.toAddress The address to transfer to
92
+ * @param options.overrides Transaction overrides, ignored if not set.
93
+ */
94
+ async transfer({
95
+ asset,
96
+ amount,
97
+ fromAddress,
98
+ toAddress,
99
+ overrides,
100
+ }: {
101
+ asset: AssetWithTokenStandard
102
+ amount?: BigNumberish
103
+ fromAddress: string
104
+ toAddress: string
105
+ overrides?: Overrides
106
+ }): Promise<void> {
107
+ overrides = { ...overrides, from: fromAddress }
108
+ let transaction: Promise<ContractTransactionResponse>
109
+
110
+ switch (asset.tokenStandard) {
111
+ case TokenStandard.ERC20: {
112
+ if (!amount) {
113
+ throw new Error("Missing ERC20 amount for transfer")
114
+ }
115
+ const contract = ERC20__factory.connect(
116
+ asset.tokenAddress,
117
+ this.context.signerOrProvider,
118
+ )
119
+ transaction = contract.transfer(toAddress, amount, overrides)
120
+ break
121
+ }
122
+ case TokenStandard.ERC1155: {
123
+ if (asset.tokenId === undefined || asset.tokenId === null) {
124
+ throw new Error("Missing ERC1155 tokenId for transfer")
125
+ }
126
+ if (!amount) {
127
+ throw new Error("Missing ERC1155 amount for transfer")
128
+ }
129
+ const contract = ERC1155__factory.connect(
130
+ asset.tokenAddress,
131
+ this.context.signerOrProvider,
132
+ )
133
+ transaction = contract.safeTransferFrom(
134
+ fromAddress,
135
+ toAddress,
136
+ asset.tokenId,
137
+ amount,
138
+ "0x",
139
+ overrides,
140
+ )
141
+ break
142
+ }
143
+ case TokenStandard.ERC721: {
144
+ if (asset.tokenId === undefined || asset.tokenId === null) {
145
+ throw new Error("Missing ERC721 tokenId for transfer")
146
+ }
147
+ const contract = ERC721__factory.connect(
148
+ asset.tokenAddress,
149
+ this.context.signerOrProvider,
150
+ )
151
+ transaction = contract.transferFrom(
152
+ fromAddress,
153
+ toAddress,
154
+ asset.tokenId,
155
+ overrides,
156
+ )
157
+ break
158
+ }
159
+ default:
160
+ throw new Error("Unsupported token standard for transfer")
161
+ }
162
+
163
+ try {
164
+ const transactionResponse = await transaction
165
+ await this.context.confirmTransaction(
166
+ transactionResponse.hash,
167
+ EventType.Transfer,
168
+ "Transferring asset",
169
+ )
170
+ } catch (error) {
171
+ console.error(error)
172
+ this.context.dispatch(EventType.TransactionDenied, {
173
+ error,
174
+ accountAddress: fromAddress,
175
+ })
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Bulk transfer multiple assets using OpenSea's TransferHelper contract.
181
+ * This method is more gas-efficient than calling transfer() multiple times.
182
+ * Note: All assets must be approved for transfer to the OpenSea conduit before calling this method.
183
+ * @param options
184
+ * @param options.assets Array of assets to transfer. Each asset must have tokenStandard set.
185
+ * @param options.fromAddress The address to transfer from
186
+ * @param options.overrides Transaction overrides, ignored if not set.
187
+ * @returns Transaction hash of the bulk transfer
188
+ *
189
+ * @throws Error if any asset is missing required fields (tokenId for NFTs, amount for ERC20/ERC1155).
190
+ * @throws Error if any asset is not approved for transfer to the OpenSea conduit.
191
+ * @throws Error if the fromAddress is not available through wallet or provider.
192
+ */
193
+ async bulkTransfer({
194
+ assets,
195
+ fromAddress,
196
+ overrides,
197
+ }: {
198
+ assets: Array<{
199
+ asset: AssetWithTokenStandard
200
+ toAddress: string
201
+ amount?: BigNumberish
202
+ }>
203
+ fromAddress: string
204
+ overrides?: Overrides
205
+ }): Promise<string> {
206
+ // Validate basic parameters before making any blockchain calls
207
+ if (assets.length === 0) {
208
+ throw new Error("At least one asset must be provided")
209
+ }
210
+
211
+ // Validate asset data and build transfer items array for TransferHelper
212
+ // This validation happens before any blockchain calls to ensure proper error messages
213
+ const transferItems: Array<{
214
+ itemType: number
215
+ token: string
216
+ identifier: string
217
+ amount: string
218
+ recipient: string
219
+ }> = []
220
+
221
+ for (const { asset, toAddress, amount } of assets) {
222
+ let itemType: number
223
+ let identifier: string
224
+ let transferAmount: string
225
+
226
+ switch (asset.tokenStandard) {
227
+ case TokenStandard.ERC20:
228
+ itemType = 1 // ERC20
229
+ identifier = "0"
230
+ if (!amount) {
231
+ throw new Error("Missing ERC20 amount for bulk transfer")
232
+ }
233
+ transferAmount = amount.toString()
234
+ break
235
+
236
+ case TokenStandard.ERC721:
237
+ itemType = 2 // ERC721
238
+ if (asset.tokenId === undefined || asset.tokenId === null) {
239
+ throw new Error("Missing ERC721 tokenId for bulk transfer")
240
+ }
241
+ identifier = asset.tokenId.toString()
242
+ transferAmount = "1"
243
+ break
244
+
245
+ case TokenStandard.ERC1155:
246
+ itemType = 3 // ERC1155
247
+ if (asset.tokenId === undefined || asset.tokenId === null) {
248
+ throw new Error("Missing ERC1155 tokenId for bulk transfer")
249
+ }
250
+ if (!amount) {
251
+ throw new Error("Missing ERC1155 amount for bulk transfer")
252
+ }
253
+ identifier = asset.tokenId.toString()
254
+ transferAmount = amount.toString()
255
+ break
256
+
257
+ default:
258
+ throw new Error(
259
+ `Unsupported token standard for bulk transfer: ${asset.tokenStandard}`,
260
+ )
261
+ }
262
+
263
+ transferItems.push({
264
+ itemType,
265
+ token: asset.tokenAddress,
266
+ identifier,
267
+ amount: transferAmount,
268
+ recipient: toAddress,
269
+ })
270
+ }
271
+
272
+ // Check account availability after parameter validation
273
+ await this.context.requireAccountIsAvailable(fromAddress)
274
+
275
+ // Get the chain-specific default conduit
276
+ const defaultConduit = getDefaultConduit(this.context.chain)
277
+
278
+ // Check approvals for all assets before attempting transfer
279
+ const unapprovedAssets: string[] = []
280
+ for (const { asset, amount } of assets) {
281
+ const isApproved = await this.checkAssetApproval(
282
+ asset,
283
+ fromAddress,
284
+ defaultConduit.address,
285
+ amount,
286
+ )
287
+ if (!isApproved) {
288
+ const assetIdentifier =
289
+ asset.tokenId !== undefined
290
+ ? `${asset.tokenAddress}:${asset.tokenId}`
291
+ : asset.tokenAddress
292
+ unapprovedAssets.push(assetIdentifier)
293
+ }
294
+ }
295
+
296
+ if (unapprovedAssets.length > 0) {
297
+ throw new Error(
298
+ `The following asset(s) are not approved for transfer to the OpenSea conduit:\n${unapprovedAssets.join("\n")}\n\n` +
299
+ `Please approve these assets before transferring. You can use the batchApproveAssets() method to approve multiple assets efficiently in a single transaction.`,
300
+ )
301
+ }
302
+
303
+ // Create TransferHelper contract instance
304
+ const transferHelper = this.getTransferHelperContract()
305
+
306
+ this.context.dispatch(EventType.Transfer, {
307
+ accountAddress: fromAddress,
308
+ assets,
309
+ })
310
+
311
+ try {
312
+ // Use chain-specific conduit key for bulk transfers
313
+ const transaction = await transferHelper.bulkTransfer(
314
+ transferItems,
315
+ defaultConduit.key,
316
+ { ...overrides, from: fromAddress },
317
+ )
318
+
319
+ await this.context.confirmTransaction(
320
+ transaction.hash,
321
+ EventType.Transfer,
322
+ `Bulk transferring ${assets.length} asset(s)`,
323
+ )
324
+
325
+ return transaction.hash
326
+ } catch (error) {
327
+ console.error(error)
328
+ this.context.dispatch(EventType.TransactionDenied, {
329
+ error,
330
+ accountAddress: fromAddress,
331
+ })
332
+ throw error
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Batch approve multiple assets for transfer to the OpenSea conduit.
338
+ * This method checks which assets need approval and batches them efficiently:
339
+ * - 0 approvals needed: Returns early
340
+ * - 1 approval needed: Sends single transaction
341
+ * - 2+ approvals needed: Uses Multicall3 to batch all approvals in one transaction
342
+ *
343
+ * @param options
344
+ * @param options.assets Array of assets to approve for transfer
345
+ * @param options.fromAddress The address that owns the assets
346
+ * @param options.overrides Transaction overrides, ignored if not set.
347
+ * @returns Transaction hash of the approval transaction, or undefined if no approvals needed
348
+ *
349
+ * @throws Error if the fromAddress is not available through wallet or provider.
350
+ */
351
+ async batchApproveAssets({
352
+ assets,
353
+ fromAddress,
354
+ overrides,
355
+ }: {
356
+ assets: Array<{
357
+ asset: AssetWithTokenStandard
358
+ amount?: BigNumberish
359
+ }>
360
+ fromAddress: string
361
+ overrides?: Overrides
362
+ }): Promise<string | undefined> {
363
+ // Validate basic parameters before making any blockchain calls
364
+ if (assets.length === 0) {
365
+ return undefined
366
+ }
367
+
368
+ // Validate ERC20 assets have amounts before making any blockchain calls
369
+ for (const { asset, amount } of assets) {
370
+ if (asset.tokenStandard === TokenStandard.ERC20 && !amount) {
371
+ throw new Error(
372
+ `Amount required for ERC20 approval: ${asset.tokenAddress}`,
373
+ )
374
+ }
375
+ }
376
+
377
+ // Check account availability after parameter validation
378
+ await this.context.requireAccountIsAvailable(fromAddress)
379
+
380
+ // Get the chain-specific default conduit
381
+ const defaultConduit = getDefaultConduit(this.context.chain)
382
+
383
+ // Check which assets need approval and build approval calldata
384
+ const approvalsNeeded: Array<{ target: string; callData: string }> = []
385
+ const processedContracts = new Set<string>()
386
+
387
+ for (const { asset, amount } of assets) {
388
+ const isApproved = await this.checkAssetApproval(
389
+ asset,
390
+ fromAddress,
391
+ defaultConduit.address,
392
+ amount,
393
+ )
394
+
395
+ if (!isApproved) {
396
+ // For ERC721/ERC1155, only approve once per contract
397
+ if (
398
+ asset.tokenStandard === TokenStandard.ERC721 ||
399
+ asset.tokenStandard === TokenStandard.ERC1155
400
+ ) {
401
+ if (processedContracts.has(asset.tokenAddress.toLowerCase())) {
402
+ continue
403
+ }
404
+ processedContracts.add(asset.tokenAddress.toLowerCase())
405
+
406
+ // setApprovalForAll(operator, true)
407
+ const iface = new ethers.Interface([
408
+ "function setApprovalForAll(address operator, bool approved)",
409
+ ])
410
+ const callData = iface.encodeFunctionData("setApprovalForAll", [
411
+ defaultConduit.address,
412
+ true,
413
+ ])
414
+ approvalsNeeded.push({
415
+ target: asset.tokenAddress,
416
+ callData,
417
+ })
418
+ } else if (asset.tokenStandard === TokenStandard.ERC20) {
419
+ // approve(spender, amount) - use max uint256 for unlimited
420
+ const iface = new ethers.Interface([
421
+ "function approve(address spender, uint256 amount) returns (bool)",
422
+ ])
423
+ const callData = iface.encodeFunctionData("approve", [
424
+ defaultConduit.address,
425
+ ethers.MaxUint256, // Approve max for convenience
426
+ ])
427
+ approvalsNeeded.push({
428
+ target: asset.tokenAddress,
429
+ callData,
430
+ })
431
+ }
432
+ }
433
+ }
434
+
435
+ // No approvals needed
436
+ if (approvalsNeeded.length === 0) {
437
+ return undefined
438
+ }
439
+
440
+ // Single approval: send directly
441
+ if (approvalsNeeded.length === 1) {
442
+ const { target, callData } = approvalsNeeded[0]
443
+ const signer = this.context.signerOrProvider as Signer
444
+ const tx = await signer.sendTransaction({
445
+ to: target,
446
+ data: callData,
447
+ ...overrides,
448
+ from: fromAddress,
449
+ })
450
+
451
+ await this.context.confirmTransaction(
452
+ tx.hash,
453
+ EventType.ApproveAllAssets,
454
+ "Approving asset for transfer",
455
+ )
456
+
457
+ return tx.hash
458
+ }
459
+
460
+ // Multiple approvals: use Multicall3
461
+ const multicall3 = this.getMulticall3Contract()
462
+
463
+ const calls = approvalsNeeded.map(({ target, callData }) => ({
464
+ target,
465
+ allowFailure: false,
466
+ callData,
467
+ }))
468
+
469
+ try {
470
+ const transaction = await multicall3.aggregate3(calls, {
471
+ ...overrides,
472
+ from: fromAddress,
473
+ })
474
+
475
+ await this.context.confirmTransaction(
476
+ transaction.hash,
477
+ EventType.ApproveAllAssets,
478
+ `Batch approving ${approvalsNeeded.length} asset(s) for transfer`,
479
+ )
480
+
481
+ return transaction.hash
482
+ } catch (error) {
483
+ console.error(error)
484
+ this.context.dispatch(EventType.TransactionDenied, {
485
+ error,
486
+ accountAddress: fromAddress,
487
+ })
488
+ throw error
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Check if an asset is approved for transfer to a specific operator (conduit).
494
+ * @param asset The asset to check approval for
495
+ * @param owner The owner address
496
+ * @param operator The operator address (conduit)
497
+ * @param amount Optional amount for ERC20 tokens
498
+ * @returns True if approved, false otherwise
499
+ */
500
+ private async checkAssetApproval(
501
+ asset: AssetWithTokenStandard,
502
+ owner: string,
503
+ operator: string,
504
+ amount?: BigNumberish,
505
+ ): Promise<boolean> {
506
+ try {
507
+ switch (asset.tokenStandard) {
508
+ case TokenStandard.ERC20: {
509
+ const contract = ERC20__factory.connect(
510
+ asset.tokenAddress,
511
+ this.context.provider,
512
+ )
513
+ const allowance = await contract.allowance.staticCall(owner, operator)
514
+ // Check if allowance is sufficient
515
+ if (!amount) {
516
+ return false
517
+ }
518
+ return allowance >= BigInt(amount.toString())
519
+ }
520
+
521
+ case TokenStandard.ERC721: {
522
+ const contract = ERC721__factory.connect(
523
+ asset.tokenAddress,
524
+ this.context.provider,
525
+ )
526
+ // Check isApprovedForAll first
527
+ const isApprovedForAll = await contract.isApprovedForAll.staticCall(
528
+ owner,
529
+ operator,
530
+ )
531
+ if (isApprovedForAll) {
532
+ return true
533
+ }
534
+ // Check individual token approval
535
+ if (asset.tokenId !== undefined && asset.tokenId !== null) {
536
+ const approved = await contract.getApproved.staticCall(
537
+ asset.tokenId,
538
+ )
539
+ return approved.toLowerCase() === operator.toLowerCase()
540
+ }
541
+ return false
542
+ }
543
+
544
+ case TokenStandard.ERC1155: {
545
+ const contract = ERC1155__factory.connect(
546
+ asset.tokenAddress,
547
+ this.context.provider,
548
+ )
549
+ return await contract.isApprovedForAll.staticCall(owner, operator)
550
+ }
551
+
552
+ default:
553
+ return false
554
+ }
555
+ } catch (error) {
556
+ // If there's an error checking approval (e.g., contract doesn't exist), return false
557
+ this.context.logger(
558
+ `Error checking approval for ${asset.tokenAddress}: ${error}`,
559
+ )
560
+ return false
561
+ }
562
+ }
563
+
564
+ /**
565
+ * Get a TransferHelper contract instance.
566
+ * @returns Contract instance for TransferHelper
567
+ */
568
+ private getTransferHelperContract(): Contract {
569
+ return new Contract(
570
+ TRANSFER_HELPER_ADDRESS,
571
+ [
572
+ "function bulkTransfer(tuple(uint8 itemType, address token, uint256 identifier, uint256 amount, address recipient)[] items, bytes32 conduitKey) external returns (bytes4)",
573
+ ],
574
+ this.context.signerOrProvider,
575
+ )
576
+ }
577
+
578
+ /**
579
+ * Get a Multicall3 contract instance.
580
+ * @returns Contract instance for Multicall3
581
+ */
582
+ private getMulticall3Contract(): Contract {
583
+ return new Contract(
584
+ MULTICALL3_ADDRESS,
585
+ [
586
+ "function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)",
587
+ ],
588
+ this.context.signerOrProvider,
589
+ )
590
+ }
591
+ }