Skip to content

Commit 744706c

Browse files
committed
feat(1657): Reject airdrop command
Signed-off-by: matevszm <mateusz.marcinkowski@blockydevs.com>
1 parent bc84c80 commit 744706c

File tree

14 files changed

+970
-1
lines changed

14 files changed

+970
-1
lines changed

.swcrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@
2525
},
2626
"baseUrl": "."
2727
}
28-
}
28+
}

docs/output-schemas-guide.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,38 @@ interface CommandOutputSpec {
399399

400400
`type` is `"FUNGIBLE"` or `"NFT"`. For FT entries `amount` is present; for NFT entries `serialNumber` is present. `hasMore: true` indicates more results exist — use `--show-all` to fetch all pages. Token name and symbol are fetched from the mirror node.
401401

402+
#### `token reject-airdrop`
403+
404+
**Output**:
405+
406+
```json
407+
{
408+
"transactionId": "0.0.123@1700000000.123456789",
409+
"ownerAccountId": "0.0.1234",
410+
"network": "testnet",
411+
"rejected": [
412+
{
413+
"tokenId": "0.0.5678",
414+
"tokenName": "FungibleToken",
415+
"tokenSymbol": "FT",
416+
"senderId": "0.0.9999",
417+
"type": "FUNGIBLE",
418+
"amount": 1000
419+
},
420+
{
421+
"tokenId": "0.0.5679",
422+
"tokenName": "MyNFT",
423+
"tokenSymbol": "NFT",
424+
"senderId": "0.0.9999",
425+
"type": "NFT",
426+
"serialNumber": 42
427+
}
428+
]
429+
}
430+
```
431+
432+
`rejected` contains the airdrops that were rejected, selected by `--index` from the `pending-airdrops` list. `type` is `"FUNGIBLE"` or `"NFT"`. For FT entries `amount` is present; for NFT entries `serialNumber` is present. Maximum 10 items per transaction (Hedera limit). Token name and symbol are fetched from the mirror node.
433+
402434
#### `token transfer-ft`
403435

404436
**Output**:

src/core/services/token/token-service.interface.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
TokenCreateTransaction,
1111
TokenDeleteTransaction,
1212
TokenMintTransaction,
13+
TokenRejectTransaction,
1314
TransferTransaction,
1415
} from '@hashgraph/sdk';
1516
import type {
@@ -23,6 +24,7 @@ import type {
2324
TokenCreateParams,
2425
TokenDeleteParams,
2526
TokenMintParams,
27+
TokenRejectAirdropParams,
2628
TokenTransferParams,
2729
} from '@/core/types/token.types';
2830

@@ -80,4 +82,8 @@ export interface TokenService {
8082
createAirdropNftTransaction(
8183
params: TokenAirdropNftParams,
8284
): TokenAirdropTransaction;
85+
86+
createRejectAirdropTransaction(
87+
params: TokenRejectAirdropParams,
88+
): TokenRejectTransaction;
8389
}

src/core/services/token/token-service.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
TokenCreateParams,
1717
TokenDeleteParams,
1818
TokenMintParams,
19+
TokenRejectAirdropParams,
1920
TokenTransferParams,
2021
} from '@/core/types/token.types';
2122
import type { TokenService } from './token-service.interface';
@@ -35,6 +36,7 @@ import {
3536
TokenDeleteTransaction,
3637
TokenId,
3738
TokenMintTransaction,
39+
TokenRejectTransaction,
3840
TokenSupplyType,
3941
TransferTransaction,
4042
} from '@hashgraph/sdk';
@@ -441,6 +443,30 @@ export class TokenServiceImpl implements TokenService {
441443
return tx;
442444
}
443445

446+
createRejectAirdropTransaction(
447+
params: TokenRejectAirdropParams,
448+
): TokenRejectTransaction {
449+
const { ownerAccountId, items } = params;
450+
const owner = AccountId.fromString(ownerAccountId);
451+
452+
this.logger.debug(
453+
`[TOKEN SERVICE] Creating reject transaction: ${items.length} item(s) for owner ${ownerAccountId}`,
454+
);
455+
456+
const tx = new TokenRejectTransaction().setOwnerId(owner);
457+
458+
for (const item of items) {
459+
const tokenId = TokenId.fromString(item.tokenId);
460+
if (item.serialNumber !== undefined) {
461+
tx.addNftId(new NftId(tokenId, item.serialNumber));
462+
} else {
463+
tx.addTokenId(tokenId);
464+
}
465+
}
466+
467+
return tx;
468+
}
469+
444470
/**
445471
* Process custom fees and convert them to Hedera CustomFee objects
446472
*/

src/core/types/token.types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,13 @@ export interface TokenAirdropNftParams {
183183
senderAccountId: string;
184184
transfers: TokenAirdropNftTransfer[];
185185
}
186+
187+
export interface RejectAirdropItem {
188+
tokenId: string;
189+
serialNumber?: number; // undefined for FT
190+
}
191+
192+
export interface TokenRejectAirdropParams {
193+
ownerAccountId: string;
194+
items: RejectAirdropItem[];
195+
}

src/plugins/token/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,53 @@ hcli token airdrop-nft \
722722

723723
**Implementation:** [`src/plugins/token/commands/airdrop-nft/handler.ts`](./commands/airdrop-nft/handler.ts)
724724

725+
### Token Reject Airdrop
726+
727+
Reject one or more pending token airdrops (FT or NFT). Rejected tokens are returned to the treasury. Custom fees are waived. Use `pending-airdrops` first to list available airdrops and their indices.
728+
729+
```bash
730+
# List pending airdrops
731+
hcli token pending-airdrops --account my-wallet
732+
733+
# Reject first pending airdrop
734+
hcli token reject-airdrop \
735+
--account my-wallet \
736+
--index 1
737+
738+
# Reject multiple airdrops (FT and/or NFT)
739+
hcli token reject-airdrop \
740+
--account my-wallet \
741+
--index 1,2,3
742+
743+
# With explicit signing key
744+
hcli token reject-airdrop \
745+
--account my-wallet \
746+
--index 1 \
747+
--from 0.0.5678:302e020100300506032b657004220420...
748+
749+
# Batch mode
750+
hcli token reject-airdrop \
751+
--account my-wallet \
752+
--index 1 \
753+
--batch my-batch
754+
```
755+
756+
**Parameters:**
757+
758+
- `--account` / `-a`: Receiver account ID or alias - **Required**
759+
- `--index` / `-i`: 1-based index(es) from `pending-airdrops` list. Comma-separated for multiple: `1,2,3` - **Required**
760+
- `--from` / `-f`: Signing account credential (alias or account-id:private-key pair) - **Optional** (defaults to operator)
761+
- `--key-manager` / `-k`: Key manager type (optional, defaults to config setting)
762+
- `local` or `local_encrypted`
763+
764+
**Notes:**
765+
766+
- Maximum 10 airdrops per transaction (Hedera limit)
767+
- Supports both fungible tokens (FT) and NFTs in a single transaction
768+
- Batch support: pass `--batch <batch-name>` to queue the transaction for batch execution
769+
770+
**Implementation:** [`src/plugins/token/commands/reject-airdrop/handler.ts`](./commands/reject-airdrop/handler.ts)
771+
725772
### Token Transfer NFT
726773

727774
Transfer one or more NFTs from one account to another.

src/plugins/token/__tests__/unit/helpers/mocks.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export const makeTokenServiceMock = (
6969
createDeleteTransaction: jest.fn(),
7070
createAirdropFtTransaction: jest.fn(),
7171
createAirdropNftTransaction: jest.fn(),
72+
createRejectAirdropTransaction: jest.fn(),
7273
...overrides,
7374
});
7475

0 commit comments

Comments
 (0)