@agether/sdk 1.2.1 → 1.4.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/dist/index.d.mts +104 -14
- package/dist/index.d.ts +104 -14
- package/dist/index.js +296 -32
- package/dist/index.mjs +296 -32
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -776,29 +776,28 @@ declare class X402Client {
|
|
|
776
776
|
/**
|
|
777
777
|
* MorphoCreditClient — SDK client for Morpho-backed overcollateralized credit
|
|
778
778
|
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
* 7. Sponsor agent by address, no borrow
|
|
787
|
-
* 8. Borrow against existing collateral (for x402 payments)
|
|
788
|
-
* 9. (Handled by X402Client.autoDraw)
|
|
779
|
+
* Full lifecycle for AI agents:
|
|
780
|
+
* - Register (ERC-8004 + AccountFactory)
|
|
781
|
+
* - Check balances and status
|
|
782
|
+
* - Deposit collateral + borrow USDC
|
|
783
|
+
* - Repay debt + withdraw collateral
|
|
784
|
+
* - Sponsor another agent
|
|
785
|
+
* - Fund AgentAccount
|
|
789
786
|
*/
|
|
790
787
|
interface MorphoCreditConfig {
|
|
791
788
|
/** Private key for signing */
|
|
792
789
|
privateKey: string;
|
|
793
790
|
/** Base RPC URL */
|
|
794
791
|
rpcUrl: string;
|
|
795
|
-
/** Agent's ERC-8004 ID */
|
|
796
|
-
agentId
|
|
792
|
+
/** Agent's ERC-8004 ID (optional — auto-resolved from chain if omitted) */
|
|
793
|
+
agentId?: string | bigint;
|
|
797
794
|
/** Contract addresses */
|
|
798
795
|
contracts: {
|
|
799
796
|
morphoCredit: string;
|
|
800
797
|
accountFactory: string;
|
|
801
798
|
usdc: string;
|
|
799
|
+
/** ERC-8004 identity registry (needed for register()) */
|
|
800
|
+
agentRegistry?: string;
|
|
802
801
|
};
|
|
803
802
|
}
|
|
804
803
|
interface CollateralToken {
|
|
@@ -863,15 +862,64 @@ interface WithdrawResult {
|
|
|
863
862
|
destination: string;
|
|
864
863
|
remainingCollateral: bigint;
|
|
865
864
|
}
|
|
865
|
+
interface RegisterResult {
|
|
866
|
+
tx: string;
|
|
867
|
+
agentId: string;
|
|
868
|
+
address: string;
|
|
869
|
+
agentAccount: string;
|
|
870
|
+
alreadyRegistered: boolean;
|
|
871
|
+
}
|
|
872
|
+
interface BalancesResult {
|
|
873
|
+
address: string;
|
|
874
|
+
agentId: string;
|
|
875
|
+
eth: string;
|
|
876
|
+
usdc: string;
|
|
877
|
+
agentAccount?: {
|
|
878
|
+
address: string;
|
|
879
|
+
eth: string;
|
|
880
|
+
usdc: string;
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
interface StatusResult {
|
|
884
|
+
agentAccount: string;
|
|
885
|
+
totalDebt: string;
|
|
886
|
+
positions: Array<{
|
|
887
|
+
token: string;
|
|
888
|
+
collateral: string;
|
|
889
|
+
debt: string;
|
|
890
|
+
active: boolean;
|
|
891
|
+
}>;
|
|
892
|
+
}
|
|
893
|
+
interface FundResult {
|
|
894
|
+
tx: string;
|
|
895
|
+
amount: string;
|
|
896
|
+
agentAccount: string;
|
|
897
|
+
}
|
|
898
|
+
interface LtvCheckResult {
|
|
899
|
+
ok: boolean;
|
|
900
|
+
currentLtv: number;
|
|
901
|
+
newLtv: number;
|
|
902
|
+
maxLtv: number;
|
|
903
|
+
collateralUsd: number;
|
|
904
|
+
currentDebt: number;
|
|
905
|
+
maxBorrow: number;
|
|
906
|
+
message?: string;
|
|
907
|
+
}
|
|
866
908
|
declare class MorphoCreditClient {
|
|
867
909
|
private signer;
|
|
868
910
|
private config;
|
|
869
911
|
private morpho;
|
|
870
912
|
private factory;
|
|
871
913
|
private accountAddress?;
|
|
914
|
+
private resolvedAgentId?;
|
|
872
915
|
private collaterals;
|
|
916
|
+
private static readonly ERC8004_ABI;
|
|
873
917
|
constructor(config: MorphoCreditConfig, collaterals?: Record<string, CollateralToken>);
|
|
874
918
|
private resolveToken;
|
|
919
|
+
/**
|
|
920
|
+
* Resolve agentId — from config, cache, or on-chain lookup.
|
|
921
|
+
*/
|
|
922
|
+
getAgentId(): Promise<string>;
|
|
875
923
|
/**
|
|
876
924
|
* Get the AgentAccount address for the configured agentId.
|
|
877
925
|
*/
|
|
@@ -881,8 +929,50 @@ declare class MorphoCreditClient {
|
|
|
881
929
|
*/
|
|
882
930
|
getAccountForAgent(agentId: string | bigint): Promise<string>;
|
|
883
931
|
private ensureCreditProvider;
|
|
932
|
+
/**
|
|
933
|
+
* Approve ERC-20 token from EOA → MorphoCredit, then deposit for account.
|
|
934
|
+
* This is 2 EOA txs (approve + depositCollateralFor) — cannot be batched
|
|
935
|
+
* because both are called from EOA, not from AgentAccount.
|
|
936
|
+
*/
|
|
884
937
|
private approveAndDeposit;
|
|
885
|
-
private
|
|
938
|
+
private morphoIface;
|
|
939
|
+
private erc20Iface;
|
|
940
|
+
/**
|
|
941
|
+
* Execute multiple calls via AgentAccount.executeBatch() in a single tx.
|
|
942
|
+
* Each call is { target, value, data }.
|
|
943
|
+
*/
|
|
944
|
+
private batch;
|
|
945
|
+
/**
|
|
946
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
947
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
948
|
+
*
|
|
949
|
+
* @param name - Agent display name
|
|
950
|
+
*/
|
|
951
|
+
register(name: string): Promise<RegisterResult>;
|
|
952
|
+
/**
|
|
953
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
954
|
+
*/
|
|
955
|
+
getBalances(): Promise<BalancesResult>;
|
|
956
|
+
/**
|
|
957
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
958
|
+
*/
|
|
959
|
+
getStatus(): Promise<StatusResult>;
|
|
960
|
+
/**
|
|
961
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
962
|
+
*
|
|
963
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
964
|
+
*/
|
|
965
|
+
fundAccount(amount: string): Promise<FundResult>;
|
|
966
|
+
private static readonly ORACLE_ABI;
|
|
967
|
+
/**
|
|
968
|
+
* Check whether a borrow would exceed max LTV.
|
|
969
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
970
|
+
*
|
|
971
|
+
* @param tokenSymbol - Collateral token
|
|
972
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
973
|
+
* @param borrowAmount - USDC to borrow
|
|
974
|
+
*/
|
|
975
|
+
checkLtv(tokenSymbol: string, additionalCollateral: string, borrowAmount: string): Promise<LtvCheckResult>;
|
|
886
976
|
/**
|
|
887
977
|
* Deposit collateral from EOA into Morpho for own AgentAccount.
|
|
888
978
|
* Does NOT borrow — use `borrow()` or `depositAndBorrow()` for that.
|
|
@@ -1123,4 +1213,4 @@ declare const VALIDATION_REGISTRY_ABI: string[];
|
|
|
1123
1213
|
declare const MORPHO_CREDIT_ABI: string[];
|
|
1124
1214
|
declare const ERC20_ABI: string[];
|
|
1125
1215
|
|
|
1126
|
-
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
|
1216
|
+
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BalancesResult, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type FundResult, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, type LtvCheckResult, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RegisterResult, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type StatusResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
package/dist/index.d.ts
CHANGED
|
@@ -776,29 +776,28 @@ declare class X402Client {
|
|
|
776
776
|
/**
|
|
777
777
|
* MorphoCreditClient — SDK client for Morpho-backed overcollateralized credit
|
|
778
778
|
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
* 7. Sponsor agent by address, no borrow
|
|
787
|
-
* 8. Borrow against existing collateral (for x402 payments)
|
|
788
|
-
* 9. (Handled by X402Client.autoDraw)
|
|
779
|
+
* Full lifecycle for AI agents:
|
|
780
|
+
* - Register (ERC-8004 + AccountFactory)
|
|
781
|
+
* - Check balances and status
|
|
782
|
+
* - Deposit collateral + borrow USDC
|
|
783
|
+
* - Repay debt + withdraw collateral
|
|
784
|
+
* - Sponsor another agent
|
|
785
|
+
* - Fund AgentAccount
|
|
789
786
|
*/
|
|
790
787
|
interface MorphoCreditConfig {
|
|
791
788
|
/** Private key for signing */
|
|
792
789
|
privateKey: string;
|
|
793
790
|
/** Base RPC URL */
|
|
794
791
|
rpcUrl: string;
|
|
795
|
-
/** Agent's ERC-8004 ID */
|
|
796
|
-
agentId
|
|
792
|
+
/** Agent's ERC-8004 ID (optional — auto-resolved from chain if omitted) */
|
|
793
|
+
agentId?: string | bigint;
|
|
797
794
|
/** Contract addresses */
|
|
798
795
|
contracts: {
|
|
799
796
|
morphoCredit: string;
|
|
800
797
|
accountFactory: string;
|
|
801
798
|
usdc: string;
|
|
799
|
+
/** ERC-8004 identity registry (needed for register()) */
|
|
800
|
+
agentRegistry?: string;
|
|
802
801
|
};
|
|
803
802
|
}
|
|
804
803
|
interface CollateralToken {
|
|
@@ -863,15 +862,64 @@ interface WithdrawResult {
|
|
|
863
862
|
destination: string;
|
|
864
863
|
remainingCollateral: bigint;
|
|
865
864
|
}
|
|
865
|
+
interface RegisterResult {
|
|
866
|
+
tx: string;
|
|
867
|
+
agentId: string;
|
|
868
|
+
address: string;
|
|
869
|
+
agentAccount: string;
|
|
870
|
+
alreadyRegistered: boolean;
|
|
871
|
+
}
|
|
872
|
+
interface BalancesResult {
|
|
873
|
+
address: string;
|
|
874
|
+
agentId: string;
|
|
875
|
+
eth: string;
|
|
876
|
+
usdc: string;
|
|
877
|
+
agentAccount?: {
|
|
878
|
+
address: string;
|
|
879
|
+
eth: string;
|
|
880
|
+
usdc: string;
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
interface StatusResult {
|
|
884
|
+
agentAccount: string;
|
|
885
|
+
totalDebt: string;
|
|
886
|
+
positions: Array<{
|
|
887
|
+
token: string;
|
|
888
|
+
collateral: string;
|
|
889
|
+
debt: string;
|
|
890
|
+
active: boolean;
|
|
891
|
+
}>;
|
|
892
|
+
}
|
|
893
|
+
interface FundResult {
|
|
894
|
+
tx: string;
|
|
895
|
+
amount: string;
|
|
896
|
+
agentAccount: string;
|
|
897
|
+
}
|
|
898
|
+
interface LtvCheckResult {
|
|
899
|
+
ok: boolean;
|
|
900
|
+
currentLtv: number;
|
|
901
|
+
newLtv: number;
|
|
902
|
+
maxLtv: number;
|
|
903
|
+
collateralUsd: number;
|
|
904
|
+
currentDebt: number;
|
|
905
|
+
maxBorrow: number;
|
|
906
|
+
message?: string;
|
|
907
|
+
}
|
|
866
908
|
declare class MorphoCreditClient {
|
|
867
909
|
private signer;
|
|
868
910
|
private config;
|
|
869
911
|
private morpho;
|
|
870
912
|
private factory;
|
|
871
913
|
private accountAddress?;
|
|
914
|
+
private resolvedAgentId?;
|
|
872
915
|
private collaterals;
|
|
916
|
+
private static readonly ERC8004_ABI;
|
|
873
917
|
constructor(config: MorphoCreditConfig, collaterals?: Record<string, CollateralToken>);
|
|
874
918
|
private resolveToken;
|
|
919
|
+
/**
|
|
920
|
+
* Resolve agentId — from config, cache, or on-chain lookup.
|
|
921
|
+
*/
|
|
922
|
+
getAgentId(): Promise<string>;
|
|
875
923
|
/**
|
|
876
924
|
* Get the AgentAccount address for the configured agentId.
|
|
877
925
|
*/
|
|
@@ -881,8 +929,50 @@ declare class MorphoCreditClient {
|
|
|
881
929
|
*/
|
|
882
930
|
getAccountForAgent(agentId: string | bigint): Promise<string>;
|
|
883
931
|
private ensureCreditProvider;
|
|
932
|
+
/**
|
|
933
|
+
* Approve ERC-20 token from EOA → MorphoCredit, then deposit for account.
|
|
934
|
+
* This is 2 EOA txs (approve + depositCollateralFor) — cannot be batched
|
|
935
|
+
* because both are called from EOA, not from AgentAccount.
|
|
936
|
+
*/
|
|
884
937
|
private approveAndDeposit;
|
|
885
|
-
private
|
|
938
|
+
private morphoIface;
|
|
939
|
+
private erc20Iface;
|
|
940
|
+
/**
|
|
941
|
+
* Execute multiple calls via AgentAccount.executeBatch() in a single tx.
|
|
942
|
+
* Each call is { target, value, data }.
|
|
943
|
+
*/
|
|
944
|
+
private batch;
|
|
945
|
+
/**
|
|
946
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
947
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
948
|
+
*
|
|
949
|
+
* @param name - Agent display name
|
|
950
|
+
*/
|
|
951
|
+
register(name: string): Promise<RegisterResult>;
|
|
952
|
+
/**
|
|
953
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
954
|
+
*/
|
|
955
|
+
getBalances(): Promise<BalancesResult>;
|
|
956
|
+
/**
|
|
957
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
958
|
+
*/
|
|
959
|
+
getStatus(): Promise<StatusResult>;
|
|
960
|
+
/**
|
|
961
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
962
|
+
*
|
|
963
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
964
|
+
*/
|
|
965
|
+
fundAccount(amount: string): Promise<FundResult>;
|
|
966
|
+
private static readonly ORACLE_ABI;
|
|
967
|
+
/**
|
|
968
|
+
* Check whether a borrow would exceed max LTV.
|
|
969
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
970
|
+
*
|
|
971
|
+
* @param tokenSymbol - Collateral token
|
|
972
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
973
|
+
* @param borrowAmount - USDC to borrow
|
|
974
|
+
*/
|
|
975
|
+
checkLtv(tokenSymbol: string, additionalCollateral: string, borrowAmount: string): Promise<LtvCheckResult>;
|
|
886
976
|
/**
|
|
887
977
|
* Deposit collateral from EOA into Morpho for own AgentAccount.
|
|
888
978
|
* Does NOT borrow — use `borrow()` or `depositAndBorrow()` for that.
|
|
@@ -1123,4 +1213,4 @@ declare const VALIDATION_REGISTRY_ABI: string[];
|
|
|
1123
1213
|
declare const MORPHO_CREDIT_ABI: string[];
|
|
1124
1214
|
declare const ERC20_ABI: string[];
|
|
1125
1215
|
|
|
1126
|
-
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
|
1216
|
+
export { ACCOUNT_FACTORY_ABI, AGENT_ACCOUNT_ABI, AGENT_REPUTATION_ABI, AgentIdentityClient, type AgentIdentityClientOptions, type AgentReputation, AgetherClient, type AgetherClientOptions, type AgetherConfig, AgetherError, type BalancesResult, type BayesianScore, type BorrowResult, CREDIT_PROVIDER_ABI, ChainId, type CollateralToken, type ContractAddresses, type CreditApplication, type CreditAppliedEvent, type CreditApprovedEvent, type CreditDrawnEvent, type CreditInfo, type CreditLine, CreditNotActiveError, type CreditRejectedEvent, type CreditRepaidEvent, CreditStatus, type DepositAndBorrowResult, type DepositResult, type DrawRequest, ERC20_ABI, type FundResult, type GraduationStatus, IDENTITY_REGISTRY_ABI, InsufficientCreditError, type LPPosition, LP_VAULT_ABI, type LoanPosition, type LtvCheckResult, MORPHO_CREDIT_ABI, MorphoCreditClient, type MorphoCreditConfig, type MorphoMarketParams, type MorphoPosition, type PaymentProof, type PaymentRequirements, type ProviderStatus, REPUTATION_CREDIT_ABI, type RegisterResult, type RepayRequest, type RepayResult, type RiskCheckResponse, type RiskFactor, type ScoreExplanation, type ScoredLimitPreview, ScoringClient, type ScoringContext, ScoringRejectedError, type ScoringRequest, type ScoringResult, type SponsorResult, type StatusResult, type TransactionResult, VALIDATION_REGISTRY_ABI, VaultClient, type VaultClientOptions, type VaultStats, WalletClient, type WalletClientConfig, type WalletInfo, type WithdrawResult, X402Client, type X402Config, type X402PaymentRequest, type X402PaymentResult, type X402Response, bpsToRate, createConfig, formatAPR, formatAddress, formatHealthFactor, formatPercent, formatTimestamp, formatUSD, formatUnits, getDefaultConfig, getUSDCAddress, parseUnits, rateToBps };
|
package/dist/index.js
CHANGED
|
@@ -150,6 +150,7 @@ var AGENT_ACCOUNT_ABI = [
|
|
|
150
150
|
"function balanceOf(address token) view returns (uint256)",
|
|
151
151
|
"function ethBalance() view returns (uint256)",
|
|
152
152
|
"function execute(address target, uint256 value, bytes data) payable returns (bytes)",
|
|
153
|
+
"function executeBatch(address[] targets, uint256[] values, bytes[] datas) payable returns (bytes[])",
|
|
153
154
|
"function drawCredit(address creditProvider, uint256 amount)",
|
|
154
155
|
"function repayCredit(address creditProvider, uint256 amount)",
|
|
155
156
|
"function fund(address token, uint256 amount)",
|
|
@@ -1509,14 +1510,18 @@ var BASE_COLLATERALS = {
|
|
|
1509
1510
|
wstETH: { symbol: "wstETH", address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", decimals: 18 },
|
|
1510
1511
|
cbETH: { symbol: "cbETH", address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", decimals: 18 }
|
|
1511
1512
|
};
|
|
1512
|
-
var
|
|
1513
|
+
var _MorphoCreditClient = class _MorphoCreditClient {
|
|
1513
1514
|
constructor(config, collaterals) {
|
|
1515
|
+
// ── Batch helper ──
|
|
1516
|
+
this.morphoIface = new import_ethers5.ethers.Interface(MORPHO_CREDIT_ABI);
|
|
1517
|
+
this.erc20Iface = new import_ethers5.ethers.Interface(ERC20_ABI);
|
|
1514
1518
|
this.config = config;
|
|
1515
1519
|
const provider = new import_ethers5.ethers.JsonRpcProvider(config.rpcUrl);
|
|
1516
1520
|
this.signer = new import_ethers5.ethers.Wallet(config.privateKey, provider);
|
|
1517
1521
|
this.morpho = new import_ethers5.Contract(config.contracts.morphoCredit, MORPHO_CREDIT_ABI, this.signer);
|
|
1518
1522
|
this.factory = new import_ethers5.Contract(config.contracts.accountFactory, ACCOUNT_FACTORY_ABI, this.signer);
|
|
1519
1523
|
this.collaterals = collaterals || BASE_COLLATERALS;
|
|
1524
|
+
if (config.agentId) this.resolvedAgentId = config.agentId.toString();
|
|
1520
1525
|
}
|
|
1521
1526
|
// ── Helpers ──
|
|
1522
1527
|
resolveToken(tokenSymbol) {
|
|
@@ -1526,12 +1531,30 @@ var MorphoCreditClient = class {
|
|
|
1526
1531
|
}
|
|
1527
1532
|
return token;
|
|
1528
1533
|
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Resolve agentId — from config, cache, or on-chain lookup.
|
|
1536
|
+
*/
|
|
1537
|
+
async getAgentId() {
|
|
1538
|
+
if (this.resolvedAgentId) return this.resolvedAgentId;
|
|
1539
|
+
if (!this.config.contracts.agentRegistry) {
|
|
1540
|
+
throw new Error("No agentId configured and no agentRegistry address to auto-resolve. Register first.");
|
|
1541
|
+
}
|
|
1542
|
+
const registry = new import_ethers5.Contract(this.config.contracts.agentRegistry, _MorphoCreditClient.ERC8004_ABI, this.signer.provider);
|
|
1543
|
+
const balance = await registry.balanceOf(this.signer.address);
|
|
1544
|
+
if (balance === 0n) {
|
|
1545
|
+
throw new Error("No agent registered. Use register() first.");
|
|
1546
|
+
}
|
|
1547
|
+
const tokenId = await registry.tokenOfOwnerByIndex(this.signer.address, 0);
|
|
1548
|
+
this.resolvedAgentId = tokenId.toString();
|
|
1549
|
+
return this.resolvedAgentId;
|
|
1550
|
+
}
|
|
1529
1551
|
/**
|
|
1530
1552
|
* Get the AgentAccount address for the configured agentId.
|
|
1531
1553
|
*/
|
|
1532
1554
|
async getAccountAddress() {
|
|
1533
1555
|
if (this.accountAddress) return this.accountAddress;
|
|
1534
|
-
const
|
|
1556
|
+
const agentId = await this.getAgentId();
|
|
1557
|
+
const addr = await this.factory.getAccount(agentId);
|
|
1535
1558
|
if (addr === import_ethers5.ethers.ZeroAddress) {
|
|
1536
1559
|
throw new Error("No AgentAccount found. Register first.");
|
|
1537
1560
|
}
|
|
@@ -1556,6 +1579,11 @@ var MorphoCreditClient = class {
|
|
|
1556
1579
|
} catch {
|
|
1557
1580
|
}
|
|
1558
1581
|
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Approve ERC-20 token from EOA → MorphoCredit, then deposit for account.
|
|
1584
|
+
* This is 2 EOA txs (approve + depositCollateralFor) — cannot be batched
|
|
1585
|
+
* because both are called from EOA, not from AgentAccount.
|
|
1586
|
+
*/
|
|
1559
1587
|
async approveAndDeposit(accountAddr, tokenInfo, amount) {
|
|
1560
1588
|
const token = new import_ethers5.Contract(tokenInfo.address, ERC20_ABI, this.signer);
|
|
1561
1589
|
const balance = await token.balanceOf(this.signer.address);
|
|
@@ -1570,15 +1598,220 @@ var MorphoCreditClient = class {
|
|
|
1570
1598
|
await depositTx.wait();
|
|
1571
1599
|
return depositTx.hash;
|
|
1572
1600
|
}
|
|
1573
|
-
|
|
1601
|
+
/**
|
|
1602
|
+
* Execute multiple calls via AgentAccount.executeBatch() in a single tx.
|
|
1603
|
+
* Each call is { target, value, data }.
|
|
1604
|
+
*/
|
|
1605
|
+
async batch(accountAddr, calls) {
|
|
1574
1606
|
const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1575
|
-
const
|
|
1576
|
-
|
|
1577
|
-
|
|
1607
|
+
const tx = await account.executeBatch(
|
|
1608
|
+
calls.map((c) => c.target),
|
|
1609
|
+
calls.map((c) => c.value),
|
|
1610
|
+
calls.map((c) => c.data)
|
|
1611
|
+
);
|
|
1578
1612
|
await tx.wait();
|
|
1579
1613
|
return tx.hash;
|
|
1580
1614
|
}
|
|
1581
1615
|
// ══════════════════════════════════════════
|
|
1616
|
+
// Register
|
|
1617
|
+
// ══════════════════════════════════════════
|
|
1618
|
+
/**
|
|
1619
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
1620
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
1621
|
+
*
|
|
1622
|
+
* @param name - Agent display name
|
|
1623
|
+
*/
|
|
1624
|
+
async register(name) {
|
|
1625
|
+
if (!this.config.contracts.agentRegistry) {
|
|
1626
|
+
throw new Error("agentRegistry address required for register()");
|
|
1627
|
+
}
|
|
1628
|
+
const registry = new import_ethers5.Contract(
|
|
1629
|
+
this.config.contracts.agentRegistry,
|
|
1630
|
+
_MorphoCreditClient.ERC8004_ABI,
|
|
1631
|
+
this.signer
|
|
1632
|
+
);
|
|
1633
|
+
if (this.resolvedAgentId) {
|
|
1634
|
+
const agentId2 = BigInt(this.resolvedAgentId);
|
|
1635
|
+
const owner = await registry.ownerOf(agentId2);
|
|
1636
|
+
if (owner.toLowerCase() !== this.signer.address.toLowerCase()) {
|
|
1637
|
+
throw new Error("agentId in config does not belong to this wallet");
|
|
1638
|
+
}
|
|
1639
|
+
const exists2 = await this.factory.accountExists(agentId2);
|
|
1640
|
+
if (!exists2) {
|
|
1641
|
+
const tx2 = await this.factory.createAccount(agentId2);
|
|
1642
|
+
await tx2.wait();
|
|
1643
|
+
}
|
|
1644
|
+
const accountAddr2 = await this.factory.getAccount(this.resolvedAgentId);
|
|
1645
|
+
return {
|
|
1646
|
+
tx: "",
|
|
1647
|
+
agentId: this.resolvedAgentId,
|
|
1648
|
+
address: this.signer.address,
|
|
1649
|
+
agentAccount: accountAddr2,
|
|
1650
|
+
alreadyRegistered: true
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
const balance = await registry.balanceOf(this.signer.address);
|
|
1654
|
+
if (balance > 0n) {
|
|
1655
|
+
const tokenId = await registry.tokenOfOwnerByIndex(this.signer.address, 0);
|
|
1656
|
+
this.resolvedAgentId = tokenId.toString();
|
|
1657
|
+
const accountAddr2 = await this.factory.getAccount(this.resolvedAgentId);
|
|
1658
|
+
return {
|
|
1659
|
+
tx: "",
|
|
1660
|
+
agentId: this.resolvedAgentId,
|
|
1661
|
+
address: this.signer.address,
|
|
1662
|
+
agentAccount: accountAddr2,
|
|
1663
|
+
alreadyRegistered: true
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
const registrationFile = JSON.stringify({
|
|
1667
|
+
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
|
|
1668
|
+
name,
|
|
1669
|
+
description: "AI agent registered via @agether/sdk",
|
|
1670
|
+
active: true,
|
|
1671
|
+
registrations: [{
|
|
1672
|
+
agentId: 0,
|
|
1673
|
+
agentRegistry: `eip155:8453:${this.config.contracts.agentRegistry}`
|
|
1674
|
+
}]
|
|
1675
|
+
});
|
|
1676
|
+
const agentURI = `data:application/json;base64,${Buffer.from(registrationFile).toString("base64")}`;
|
|
1677
|
+
const tx = await registry["register(string)"](agentURI);
|
|
1678
|
+
const receipt = await tx.wait();
|
|
1679
|
+
const transferTopic = import_ethers5.ethers.id("Transfer(address,address,uint256)");
|
|
1680
|
+
const transferLog = receipt.logs.find((l) => l.topics[0] === transferTopic);
|
|
1681
|
+
if (!transferLog?.topics?.[3]) {
|
|
1682
|
+
throw new Error("Could not parse agentId from receipt");
|
|
1683
|
+
}
|
|
1684
|
+
const agentId = BigInt(transferLog.topics[3]);
|
|
1685
|
+
this.resolvedAgentId = agentId.toString();
|
|
1686
|
+
const exists = await this.factory.accountExists(agentId);
|
|
1687
|
+
if (!exists) {
|
|
1688
|
+
const accTx = await this.factory.createAccount(agentId);
|
|
1689
|
+
await accTx.wait();
|
|
1690
|
+
}
|
|
1691
|
+
const accountAddr = await this.factory.getAccount(this.resolvedAgentId);
|
|
1692
|
+
this.accountAddress = accountAddr;
|
|
1693
|
+
return {
|
|
1694
|
+
tx: tx.hash,
|
|
1695
|
+
agentId: this.resolvedAgentId,
|
|
1696
|
+
address: this.signer.address,
|
|
1697
|
+
agentAccount: accountAddr,
|
|
1698
|
+
alreadyRegistered: false
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
// ══════════════════════════════════════════
|
|
1702
|
+
// Balances & Status
|
|
1703
|
+
// ══════════════════════════════════════════
|
|
1704
|
+
/**
|
|
1705
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
1706
|
+
*/
|
|
1707
|
+
async getBalances() {
|
|
1708
|
+
const provider = this.signer.provider;
|
|
1709
|
+
const ethBal = await provider.getBalance(this.signer.address);
|
|
1710
|
+
const usdc = new import_ethers5.Contract(this.config.contracts.usdc, ERC20_ABI, provider);
|
|
1711
|
+
const usdcBal = await usdc.balanceOf(this.signer.address);
|
|
1712
|
+
const result = {
|
|
1713
|
+
address: this.signer.address,
|
|
1714
|
+
agentId: this.resolvedAgentId || "not registered",
|
|
1715
|
+
eth: import_ethers5.ethers.formatEther(ethBal),
|
|
1716
|
+
usdc: import_ethers5.ethers.formatUnits(usdcBal, 6)
|
|
1717
|
+
};
|
|
1718
|
+
try {
|
|
1719
|
+
const accountAddr = await this.getAccountAddress();
|
|
1720
|
+
const accEth = await provider.getBalance(accountAddr);
|
|
1721
|
+
const accUsdc = await usdc.balanceOf(accountAddr);
|
|
1722
|
+
result.agentAccount = {
|
|
1723
|
+
address: accountAddr,
|
|
1724
|
+
eth: import_ethers5.ethers.formatEther(accEth),
|
|
1725
|
+
usdc: import_ethers5.ethers.formatUnits(accUsdc, 6)
|
|
1726
|
+
};
|
|
1727
|
+
} catch {
|
|
1728
|
+
}
|
|
1729
|
+
return result;
|
|
1730
|
+
}
|
|
1731
|
+
/**
|
|
1732
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
1733
|
+
*/
|
|
1734
|
+
async getStatus() {
|
|
1735
|
+
const accountAddr = await this.getAccountAddress();
|
|
1736
|
+
const positions = [];
|
|
1737
|
+
for (const [symbol, info] of Object.entries(this.collaterals)) {
|
|
1738
|
+
const pos = await this.morpho.getPosition(accountAddr, info.address);
|
|
1739
|
+
if (pos.isActive || pos.collateralAmount > 0n || pos.borrowedAmount > 0n) {
|
|
1740
|
+
positions.push({
|
|
1741
|
+
token: symbol,
|
|
1742
|
+
collateral: import_ethers5.ethers.formatUnits(pos.collateralAmount, info.decimals),
|
|
1743
|
+
debt: `$${import_ethers5.ethers.formatUnits(pos.borrowedAmount, 6)}`,
|
|
1744
|
+
active: pos.isActive
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1749
|
+
return {
|
|
1750
|
+
agentAccount: accountAddr,
|
|
1751
|
+
totalDebt: `$${import_ethers5.ethers.formatUnits(totalDebt, 6)}`,
|
|
1752
|
+
positions
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
// ══════════════════════════════════════════
|
|
1756
|
+
// Fund AgentAccount
|
|
1757
|
+
// ══════════════════════════════════════════
|
|
1758
|
+
/**
|
|
1759
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
1760
|
+
*
|
|
1761
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
1762
|
+
*/
|
|
1763
|
+
async fundAccount(amount) {
|
|
1764
|
+
const amountWei = import_ethers5.ethers.parseUnits(amount, 6);
|
|
1765
|
+
const accountAddr = await this.getAccountAddress();
|
|
1766
|
+
const usdc = new import_ethers5.Contract(this.config.contracts.usdc, ERC20_ABI, this.signer);
|
|
1767
|
+
const balance = await usdc.balanceOf(this.signer.address);
|
|
1768
|
+
if (balance < amountWei) {
|
|
1769
|
+
throw new Error(`Insufficient USDC: have $${import_ethers5.ethers.formatUnits(balance, 6)}, need $${amount}`);
|
|
1770
|
+
}
|
|
1771
|
+
const tx = await usdc.transfer(accountAddr, amountWei);
|
|
1772
|
+
await tx.wait();
|
|
1773
|
+
return { tx: tx.hash, amount, agentAccount: accountAddr };
|
|
1774
|
+
}
|
|
1775
|
+
/**
|
|
1776
|
+
* Check whether a borrow would exceed max LTV.
|
|
1777
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
1778
|
+
*
|
|
1779
|
+
* @param tokenSymbol - Collateral token
|
|
1780
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
1781
|
+
* @param borrowAmount - USDC to borrow
|
|
1782
|
+
*/
|
|
1783
|
+
async checkLtv(tokenSymbol, additionalCollateral, borrowAmount) {
|
|
1784
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1785
|
+
const accountAddr = await this.getAccountAddress();
|
|
1786
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1787
|
+
const marketInfo = await this.morpho.markets(tokenInfo.address);
|
|
1788
|
+
const oracle = new import_ethers5.Contract(marketInfo.params.oracle, _MorphoCreditClient.ORACLE_ABI, this.signer.provider);
|
|
1789
|
+
const oraclePrice = await oracle.price();
|
|
1790
|
+
const addCollateralWei = import_ethers5.ethers.parseUnits(additionalCollateral, tokenInfo.decimals);
|
|
1791
|
+
const borrowWei = import_ethers5.ethers.parseUnits(borrowAmount, 6);
|
|
1792
|
+
const totalCollateral = pos.collateralAmount + addCollateralWei;
|
|
1793
|
+
const totalDebt = pos.borrowedAmount + borrowWei;
|
|
1794
|
+
const collateralValue = totalCollateral * oraclePrice / BigInt("1000000000000000000000000000000000000");
|
|
1795
|
+
const collateralUsd = Number(collateralValue) / 1e6;
|
|
1796
|
+
const currentDebtUsd = Number(pos.borrowedAmount) / 1e6;
|
|
1797
|
+
const maxLtvBps = Number(marketInfo.maxLtvBps);
|
|
1798
|
+
const currentLtv = collateralValue > 0n ? Number(pos.borrowedAmount * 10000n / collateralValue) / 100 : 0;
|
|
1799
|
+
const newLtv = collateralValue > 0n ? Number(totalDebt * 10000n / collateralValue) / 100 : totalDebt > 0n ? Infinity : 0;
|
|
1800
|
+
const maxLtv = maxLtvBps / 100;
|
|
1801
|
+
const maxBorrow = collateralUsd * maxLtvBps / 1e4;
|
|
1802
|
+
const ok = newLtv <= maxLtv;
|
|
1803
|
+
return {
|
|
1804
|
+
ok,
|
|
1805
|
+
currentLtv,
|
|
1806
|
+
newLtv,
|
|
1807
|
+
maxLtv,
|
|
1808
|
+
collateralUsd,
|
|
1809
|
+
currentDebt: currentDebtUsd,
|
|
1810
|
+
maxBorrow,
|
|
1811
|
+
message: ok ? void 0 : `ExceedsMaxLtv: borrowing $${borrowAmount} would push LTV to ${newLtv.toFixed(1)}% (max ${maxLtv}%). Collateral: $${collateralUsd.toFixed(2)}. Current debt: $${currentDebtUsd.toFixed(3)}. Max additional borrow: $${(maxBorrow - currentDebtUsd).toFixed(2)}. Deposit more collateral or borrow less.`
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
// ══════════════════════════════════════════
|
|
1582
1815
|
// Flow 3: Deposit collateral only
|
|
1583
1816
|
// ══════════════════════════════════════════
|
|
1584
1817
|
/**
|
|
@@ -1619,13 +1852,18 @@ var MorphoCreditClient = class {
|
|
|
1619
1852
|
const collateralWei = import_ethers5.ethers.parseUnits(collateralAmount, tokenInfo.decimals);
|
|
1620
1853
|
const borrowWei = import_ethers5.ethers.parseUnits(borrowAmount, 6);
|
|
1621
1854
|
const accountAddr = await this.getAccountAddress();
|
|
1855
|
+
const ltvCheck = await this.checkLtv(tokenSymbol, collateralAmount, borrowAmount);
|
|
1856
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1622
1857
|
const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
|
|
1623
1858
|
await this.ensureCreditProvider(accountAddr);
|
|
1624
|
-
const
|
|
1859
|
+
const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1860
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
|
|
1861
|
+
const borrowTx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1862
|
+
await borrowTx.wait();
|
|
1625
1863
|
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1626
1864
|
return {
|
|
1627
1865
|
depositTx: depositTxHash,
|
|
1628
|
-
borrowTx:
|
|
1866
|
+
borrowTx: borrowTx.hash,
|
|
1629
1867
|
collateral: { amount: collateralWei, token: tokenSymbol },
|
|
1630
1868
|
borrowed: borrowWei,
|
|
1631
1869
|
agentAccount: accountAddr,
|
|
@@ -1656,10 +1894,16 @@ var MorphoCreditClient = class {
|
|
|
1656
1894
|
if (!activeToken) {
|
|
1657
1895
|
throw new Error("No collateral deposited. Use deposit() or depositAndBorrow() first.");
|
|
1658
1896
|
}
|
|
1659
|
-
const
|
|
1897
|
+
const ltvCheck = await this.checkLtv(activeToken.symbol, "0", amount);
|
|
1898
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1899
|
+
await this.ensureCreditProvider(accountAddr);
|
|
1900
|
+
const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1901
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [activeToken.address, borrowWei]);
|
|
1902
|
+
const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1903
|
+
await tx.wait();
|
|
1660
1904
|
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1661
1905
|
return {
|
|
1662
|
-
tx:
|
|
1906
|
+
tx: tx.hash,
|
|
1663
1907
|
amount: borrowWei,
|
|
1664
1908
|
agentAccount: accountAddr,
|
|
1665
1909
|
totalDebt,
|
|
@@ -1704,8 +1948,11 @@ var MorphoCreditClient = class {
|
|
|
1704
1948
|
const borrowWei = import_ethers5.ethers.parseUnits(borrowAmount, 6);
|
|
1705
1949
|
try {
|
|
1706
1950
|
await this.ensureCreditProvider(accountAddr);
|
|
1707
|
-
const
|
|
1708
|
-
|
|
1951
|
+
const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1952
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
|
|
1953
|
+
const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1954
|
+
await tx.wait();
|
|
1955
|
+
result.borrowTx = tx.hash;
|
|
1709
1956
|
result.borrowed = borrowWei;
|
|
1710
1957
|
} catch (e) {
|
|
1711
1958
|
throw new Error(`Borrow failed (caller may not own this AgentAccount): ${e.message}`);
|
|
@@ -1741,17 +1988,20 @@ var MorphoCreditClient = class {
|
|
|
1741
1988
|
if (balance < amountWei) {
|
|
1742
1989
|
throw new Error(`Insufficient USDC in AgentAccount: $${import_ethers5.ethers.formatUnits(balance, 6)}`);
|
|
1743
1990
|
}
|
|
1744
|
-
const
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1991
|
+
const txHash = await this.batch(accountAddr, [
|
|
1992
|
+
{
|
|
1993
|
+
target: this.config.contracts.usdc,
|
|
1994
|
+
value: 0n,
|
|
1995
|
+
data: this.erc20Iface.encodeFunctionData("approve", [this.config.contracts.morphoCredit, amountWei])
|
|
1996
|
+
},
|
|
1997
|
+
{
|
|
1998
|
+
target: this.config.contracts.morphoCredit,
|
|
1999
|
+
value: 0n,
|
|
2000
|
+
data: this.morphoIface.encodeFunctionData("repayWithCollateral", [collateralAddr, amountWei])
|
|
2001
|
+
}
|
|
2002
|
+
]);
|
|
1753
2003
|
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1754
|
-
return { tx:
|
|
2004
|
+
return { tx: txHash, amount: amountWei, remainingDebt: totalDebt };
|
|
1755
2005
|
}
|
|
1756
2006
|
/**
|
|
1757
2007
|
* Withdraw collateral from Morpho back to EOA.
|
|
@@ -1772,18 +2022,21 @@ var MorphoCreditClient = class {
|
|
|
1772
2022
|
`Cannot withdraw more than deposited: max ${import_ethers5.ethers.formatUnits(pos.collateralAmount, tokenInfo.decimals)} ${tokenSymbol}`
|
|
1773
2023
|
);
|
|
1774
2024
|
}
|
|
1775
|
-
const
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
2025
|
+
const txHash = await this.batch(accountAddr, [
|
|
2026
|
+
{
|
|
2027
|
+
target: this.config.contracts.morphoCredit,
|
|
2028
|
+
value: 0n,
|
|
2029
|
+
data: this.morphoIface.encodeFunctionData("withdrawCollateral", [tokenInfo.address, withdrawAmount])
|
|
2030
|
+
},
|
|
2031
|
+
{
|
|
2032
|
+
target: tokenInfo.address,
|
|
2033
|
+
value: 0n,
|
|
2034
|
+
data: this.erc20Iface.encodeFunctionData("transfer", [this.signer.address, withdrawAmount])
|
|
2035
|
+
}
|
|
2036
|
+
]);
|
|
1784
2037
|
const newPos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1785
2038
|
return {
|
|
1786
|
-
tx:
|
|
2039
|
+
tx: txHash,
|
|
1787
2040
|
amount: withdrawAmount,
|
|
1788
2041
|
token: tokenSymbol,
|
|
1789
2042
|
destination: this.signer.address,
|
|
@@ -1848,6 +2101,17 @@ var MorphoCreditClient = class {
|
|
|
1848
2101
|
return this.signer.address;
|
|
1849
2102
|
}
|
|
1850
2103
|
};
|
|
2104
|
+
_MorphoCreditClient.ERC8004_ABI = [
|
|
2105
|
+
"function register(string agentURI) returns (uint256)",
|
|
2106
|
+
"function ownerOf(uint256 tokenId) view returns (address)",
|
|
2107
|
+
"function balanceOf(address owner) view returns (uint256)",
|
|
2108
|
+
"function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)"
|
|
2109
|
+
];
|
|
2110
|
+
// ══════════════════════════════════════════
|
|
2111
|
+
// LTV Pre-check
|
|
2112
|
+
// ══════════════════════════════════════════
|
|
2113
|
+
_MorphoCreditClient.ORACLE_ABI = ["function price() view returns (uint256)"];
|
|
2114
|
+
var MorphoCreditClient = _MorphoCreditClient;
|
|
1851
2115
|
|
|
1852
2116
|
// src/clients/WalletClient.ts
|
|
1853
2117
|
var import_ethers6 = require("ethers");
|
package/dist/index.mjs
CHANGED
|
@@ -79,6 +79,7 @@ var AGENT_ACCOUNT_ABI = [
|
|
|
79
79
|
"function balanceOf(address token) view returns (uint256)",
|
|
80
80
|
"function ethBalance() view returns (uint256)",
|
|
81
81
|
"function execute(address target, uint256 value, bytes data) payable returns (bytes)",
|
|
82
|
+
"function executeBatch(address[] targets, uint256[] values, bytes[] datas) payable returns (bytes[])",
|
|
82
83
|
"function drawCredit(address creditProvider, uint256 amount)",
|
|
83
84
|
"function repayCredit(address creditProvider, uint256 amount)",
|
|
84
85
|
"function fund(address token, uint256 amount)",
|
|
@@ -1438,14 +1439,18 @@ var BASE_COLLATERALS = {
|
|
|
1438
1439
|
wstETH: { symbol: "wstETH", address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", decimals: 18 },
|
|
1439
1440
|
cbETH: { symbol: "cbETH", address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", decimals: 18 }
|
|
1440
1441
|
};
|
|
1441
|
-
var
|
|
1442
|
+
var _MorphoCreditClient = class _MorphoCreditClient {
|
|
1442
1443
|
constructor(config, collaterals) {
|
|
1444
|
+
// ── Batch helper ──
|
|
1445
|
+
this.morphoIface = new ethers4.Interface(MORPHO_CREDIT_ABI);
|
|
1446
|
+
this.erc20Iface = new ethers4.Interface(ERC20_ABI);
|
|
1443
1447
|
this.config = config;
|
|
1444
1448
|
const provider = new ethers4.JsonRpcProvider(config.rpcUrl);
|
|
1445
1449
|
this.signer = new ethers4.Wallet(config.privateKey, provider);
|
|
1446
1450
|
this.morpho = new Contract3(config.contracts.morphoCredit, MORPHO_CREDIT_ABI, this.signer);
|
|
1447
1451
|
this.factory = new Contract3(config.contracts.accountFactory, ACCOUNT_FACTORY_ABI, this.signer);
|
|
1448
1452
|
this.collaterals = collaterals || BASE_COLLATERALS;
|
|
1453
|
+
if (config.agentId) this.resolvedAgentId = config.agentId.toString();
|
|
1449
1454
|
}
|
|
1450
1455
|
// ── Helpers ──
|
|
1451
1456
|
resolveToken(tokenSymbol) {
|
|
@@ -1455,12 +1460,30 @@ var MorphoCreditClient = class {
|
|
|
1455
1460
|
}
|
|
1456
1461
|
return token;
|
|
1457
1462
|
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Resolve agentId — from config, cache, or on-chain lookup.
|
|
1465
|
+
*/
|
|
1466
|
+
async getAgentId() {
|
|
1467
|
+
if (this.resolvedAgentId) return this.resolvedAgentId;
|
|
1468
|
+
if (!this.config.contracts.agentRegistry) {
|
|
1469
|
+
throw new Error("No agentId configured and no agentRegistry address to auto-resolve. Register first.");
|
|
1470
|
+
}
|
|
1471
|
+
const registry = new Contract3(this.config.contracts.agentRegistry, _MorphoCreditClient.ERC8004_ABI, this.signer.provider);
|
|
1472
|
+
const balance = await registry.balanceOf(this.signer.address);
|
|
1473
|
+
if (balance === 0n) {
|
|
1474
|
+
throw new Error("No agent registered. Use register() first.");
|
|
1475
|
+
}
|
|
1476
|
+
const tokenId = await registry.tokenOfOwnerByIndex(this.signer.address, 0);
|
|
1477
|
+
this.resolvedAgentId = tokenId.toString();
|
|
1478
|
+
return this.resolvedAgentId;
|
|
1479
|
+
}
|
|
1458
1480
|
/**
|
|
1459
1481
|
* Get the AgentAccount address for the configured agentId.
|
|
1460
1482
|
*/
|
|
1461
1483
|
async getAccountAddress() {
|
|
1462
1484
|
if (this.accountAddress) return this.accountAddress;
|
|
1463
|
-
const
|
|
1485
|
+
const agentId = await this.getAgentId();
|
|
1486
|
+
const addr = await this.factory.getAccount(agentId);
|
|
1464
1487
|
if (addr === ethers4.ZeroAddress) {
|
|
1465
1488
|
throw new Error("No AgentAccount found. Register first.");
|
|
1466
1489
|
}
|
|
@@ -1485,6 +1508,11 @@ var MorphoCreditClient = class {
|
|
|
1485
1508
|
} catch {
|
|
1486
1509
|
}
|
|
1487
1510
|
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Approve ERC-20 token from EOA → MorphoCredit, then deposit for account.
|
|
1513
|
+
* This is 2 EOA txs (approve + depositCollateralFor) — cannot be batched
|
|
1514
|
+
* because both are called from EOA, not from AgentAccount.
|
|
1515
|
+
*/
|
|
1488
1516
|
async approveAndDeposit(accountAddr, tokenInfo, amount) {
|
|
1489
1517
|
const token = new Contract3(tokenInfo.address, ERC20_ABI, this.signer);
|
|
1490
1518
|
const balance = await token.balanceOf(this.signer.address);
|
|
@@ -1499,15 +1527,220 @@ var MorphoCreditClient = class {
|
|
|
1499
1527
|
await depositTx.wait();
|
|
1500
1528
|
return depositTx.hash;
|
|
1501
1529
|
}
|
|
1502
|
-
|
|
1530
|
+
/**
|
|
1531
|
+
* Execute multiple calls via AgentAccount.executeBatch() in a single tx.
|
|
1532
|
+
* Each call is { target, value, data }.
|
|
1533
|
+
*/
|
|
1534
|
+
async batch(accountAddr, calls) {
|
|
1503
1535
|
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1504
|
-
const
|
|
1505
|
-
|
|
1506
|
-
|
|
1536
|
+
const tx = await account.executeBatch(
|
|
1537
|
+
calls.map((c) => c.target),
|
|
1538
|
+
calls.map((c) => c.value),
|
|
1539
|
+
calls.map((c) => c.data)
|
|
1540
|
+
);
|
|
1507
1541
|
await tx.wait();
|
|
1508
1542
|
return tx.hash;
|
|
1509
1543
|
}
|
|
1510
1544
|
// ══════════════════════════════════════════
|
|
1545
|
+
// Register
|
|
1546
|
+
// ══════════════════════════════════════════
|
|
1547
|
+
/**
|
|
1548
|
+
* Register a new ERC-8004 agent identity and create an AgentAccount.
|
|
1549
|
+
* If already registered (agentId in config or on-chain), returns existing info.
|
|
1550
|
+
*
|
|
1551
|
+
* @param name - Agent display name
|
|
1552
|
+
*/
|
|
1553
|
+
async register(name) {
|
|
1554
|
+
if (!this.config.contracts.agentRegistry) {
|
|
1555
|
+
throw new Error("agentRegistry address required for register()");
|
|
1556
|
+
}
|
|
1557
|
+
const registry = new Contract3(
|
|
1558
|
+
this.config.contracts.agentRegistry,
|
|
1559
|
+
_MorphoCreditClient.ERC8004_ABI,
|
|
1560
|
+
this.signer
|
|
1561
|
+
);
|
|
1562
|
+
if (this.resolvedAgentId) {
|
|
1563
|
+
const agentId2 = BigInt(this.resolvedAgentId);
|
|
1564
|
+
const owner = await registry.ownerOf(agentId2);
|
|
1565
|
+
if (owner.toLowerCase() !== this.signer.address.toLowerCase()) {
|
|
1566
|
+
throw new Error("agentId in config does not belong to this wallet");
|
|
1567
|
+
}
|
|
1568
|
+
const exists2 = await this.factory.accountExists(agentId2);
|
|
1569
|
+
if (!exists2) {
|
|
1570
|
+
const tx2 = await this.factory.createAccount(agentId2);
|
|
1571
|
+
await tx2.wait();
|
|
1572
|
+
}
|
|
1573
|
+
const accountAddr2 = await this.factory.getAccount(this.resolvedAgentId);
|
|
1574
|
+
return {
|
|
1575
|
+
tx: "",
|
|
1576
|
+
agentId: this.resolvedAgentId,
|
|
1577
|
+
address: this.signer.address,
|
|
1578
|
+
agentAccount: accountAddr2,
|
|
1579
|
+
alreadyRegistered: true
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
const balance = await registry.balanceOf(this.signer.address);
|
|
1583
|
+
if (balance > 0n) {
|
|
1584
|
+
const tokenId = await registry.tokenOfOwnerByIndex(this.signer.address, 0);
|
|
1585
|
+
this.resolvedAgentId = tokenId.toString();
|
|
1586
|
+
const accountAddr2 = await this.factory.getAccount(this.resolvedAgentId);
|
|
1587
|
+
return {
|
|
1588
|
+
tx: "",
|
|
1589
|
+
agentId: this.resolvedAgentId,
|
|
1590
|
+
address: this.signer.address,
|
|
1591
|
+
agentAccount: accountAddr2,
|
|
1592
|
+
alreadyRegistered: true
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
const registrationFile = JSON.stringify({
|
|
1596
|
+
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
|
|
1597
|
+
name,
|
|
1598
|
+
description: "AI agent registered via @agether/sdk",
|
|
1599
|
+
active: true,
|
|
1600
|
+
registrations: [{
|
|
1601
|
+
agentId: 0,
|
|
1602
|
+
agentRegistry: `eip155:8453:${this.config.contracts.agentRegistry}`
|
|
1603
|
+
}]
|
|
1604
|
+
});
|
|
1605
|
+
const agentURI = `data:application/json;base64,${Buffer.from(registrationFile).toString("base64")}`;
|
|
1606
|
+
const tx = await registry["register(string)"](agentURI);
|
|
1607
|
+
const receipt = await tx.wait();
|
|
1608
|
+
const transferTopic = ethers4.id("Transfer(address,address,uint256)");
|
|
1609
|
+
const transferLog = receipt.logs.find((l) => l.topics[0] === transferTopic);
|
|
1610
|
+
if (!transferLog?.topics?.[3]) {
|
|
1611
|
+
throw new Error("Could not parse agentId from receipt");
|
|
1612
|
+
}
|
|
1613
|
+
const agentId = BigInt(transferLog.topics[3]);
|
|
1614
|
+
this.resolvedAgentId = agentId.toString();
|
|
1615
|
+
const exists = await this.factory.accountExists(agentId);
|
|
1616
|
+
if (!exists) {
|
|
1617
|
+
const accTx = await this.factory.createAccount(agentId);
|
|
1618
|
+
await accTx.wait();
|
|
1619
|
+
}
|
|
1620
|
+
const accountAddr = await this.factory.getAccount(this.resolvedAgentId);
|
|
1621
|
+
this.accountAddress = accountAddr;
|
|
1622
|
+
return {
|
|
1623
|
+
tx: tx.hash,
|
|
1624
|
+
agentId: this.resolvedAgentId,
|
|
1625
|
+
address: this.signer.address,
|
|
1626
|
+
agentAccount: accountAddr,
|
|
1627
|
+
alreadyRegistered: false
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
// ══════════════════════════════════════════
|
|
1631
|
+
// Balances & Status
|
|
1632
|
+
// ══════════════════════════════════════════
|
|
1633
|
+
/**
|
|
1634
|
+
* Get ETH and USDC balances for EOA wallet and AgentAccount.
|
|
1635
|
+
*/
|
|
1636
|
+
async getBalances() {
|
|
1637
|
+
const provider = this.signer.provider;
|
|
1638
|
+
const ethBal = await provider.getBalance(this.signer.address);
|
|
1639
|
+
const usdc = new Contract3(this.config.contracts.usdc, ERC20_ABI, provider);
|
|
1640
|
+
const usdcBal = await usdc.balanceOf(this.signer.address);
|
|
1641
|
+
const result = {
|
|
1642
|
+
address: this.signer.address,
|
|
1643
|
+
agentId: this.resolvedAgentId || "not registered",
|
|
1644
|
+
eth: ethers4.formatEther(ethBal),
|
|
1645
|
+
usdc: ethers4.formatUnits(usdcBal, 6)
|
|
1646
|
+
};
|
|
1647
|
+
try {
|
|
1648
|
+
const accountAddr = await this.getAccountAddress();
|
|
1649
|
+
const accEth = await provider.getBalance(accountAddr);
|
|
1650
|
+
const accUsdc = await usdc.balanceOf(accountAddr);
|
|
1651
|
+
result.agentAccount = {
|
|
1652
|
+
address: accountAddr,
|
|
1653
|
+
eth: ethers4.formatEther(accEth),
|
|
1654
|
+
usdc: ethers4.formatUnits(accUsdc, 6)
|
|
1655
|
+
};
|
|
1656
|
+
} catch {
|
|
1657
|
+
}
|
|
1658
|
+
return result;
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Get full Morpho credit status — all positions + total debt.
|
|
1662
|
+
*/
|
|
1663
|
+
async getStatus() {
|
|
1664
|
+
const accountAddr = await this.getAccountAddress();
|
|
1665
|
+
const positions = [];
|
|
1666
|
+
for (const [symbol, info] of Object.entries(this.collaterals)) {
|
|
1667
|
+
const pos = await this.morpho.getPosition(accountAddr, info.address);
|
|
1668
|
+
if (pos.isActive || pos.collateralAmount > 0n || pos.borrowedAmount > 0n) {
|
|
1669
|
+
positions.push({
|
|
1670
|
+
token: symbol,
|
|
1671
|
+
collateral: ethers4.formatUnits(pos.collateralAmount, info.decimals),
|
|
1672
|
+
debt: `$${ethers4.formatUnits(pos.borrowedAmount, 6)}`,
|
|
1673
|
+
active: pos.isActive
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1678
|
+
return {
|
|
1679
|
+
agentAccount: accountAddr,
|
|
1680
|
+
totalDebt: `$${ethers4.formatUnits(totalDebt, 6)}`,
|
|
1681
|
+
positions
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
// ══════════════════════════════════════════
|
|
1685
|
+
// Fund AgentAccount
|
|
1686
|
+
// ══════════════════════════════════════════
|
|
1687
|
+
/**
|
|
1688
|
+
* Transfer USDC from EOA wallet into AgentAccount.
|
|
1689
|
+
*
|
|
1690
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
1691
|
+
*/
|
|
1692
|
+
async fundAccount(amount) {
|
|
1693
|
+
const amountWei = ethers4.parseUnits(amount, 6);
|
|
1694
|
+
const accountAddr = await this.getAccountAddress();
|
|
1695
|
+
const usdc = new Contract3(this.config.contracts.usdc, ERC20_ABI, this.signer);
|
|
1696
|
+
const balance = await usdc.balanceOf(this.signer.address);
|
|
1697
|
+
if (balance < amountWei) {
|
|
1698
|
+
throw new Error(`Insufficient USDC: have $${ethers4.formatUnits(balance, 6)}, need $${amount}`);
|
|
1699
|
+
}
|
|
1700
|
+
const tx = await usdc.transfer(accountAddr, amountWei);
|
|
1701
|
+
await tx.wait();
|
|
1702
|
+
return { tx: tx.hash, amount, agentAccount: accountAddr };
|
|
1703
|
+
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Check whether a borrow would exceed max LTV.
|
|
1706
|
+
* Call before borrow() or depositAndBorrow() to get a clear error instead of on-chain revert.
|
|
1707
|
+
*
|
|
1708
|
+
* @param tokenSymbol - Collateral token
|
|
1709
|
+
* @param additionalCollateral - Additional collateral being deposited ("0" if just borrowing)
|
|
1710
|
+
* @param borrowAmount - USDC to borrow
|
|
1711
|
+
*/
|
|
1712
|
+
async checkLtv(tokenSymbol, additionalCollateral, borrowAmount) {
|
|
1713
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1714
|
+
const accountAddr = await this.getAccountAddress();
|
|
1715
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1716
|
+
const marketInfo = await this.morpho.markets(tokenInfo.address);
|
|
1717
|
+
const oracle = new Contract3(marketInfo.params.oracle, _MorphoCreditClient.ORACLE_ABI, this.signer.provider);
|
|
1718
|
+
const oraclePrice = await oracle.price();
|
|
1719
|
+
const addCollateralWei = ethers4.parseUnits(additionalCollateral, tokenInfo.decimals);
|
|
1720
|
+
const borrowWei = ethers4.parseUnits(borrowAmount, 6);
|
|
1721
|
+
const totalCollateral = pos.collateralAmount + addCollateralWei;
|
|
1722
|
+
const totalDebt = pos.borrowedAmount + borrowWei;
|
|
1723
|
+
const collateralValue = totalCollateral * oraclePrice / BigInt("1000000000000000000000000000000000000");
|
|
1724
|
+
const collateralUsd = Number(collateralValue) / 1e6;
|
|
1725
|
+
const currentDebtUsd = Number(pos.borrowedAmount) / 1e6;
|
|
1726
|
+
const maxLtvBps = Number(marketInfo.maxLtvBps);
|
|
1727
|
+
const currentLtv = collateralValue > 0n ? Number(pos.borrowedAmount * 10000n / collateralValue) / 100 : 0;
|
|
1728
|
+
const newLtv = collateralValue > 0n ? Number(totalDebt * 10000n / collateralValue) / 100 : totalDebt > 0n ? Infinity : 0;
|
|
1729
|
+
const maxLtv = maxLtvBps / 100;
|
|
1730
|
+
const maxBorrow = collateralUsd * maxLtvBps / 1e4;
|
|
1731
|
+
const ok = newLtv <= maxLtv;
|
|
1732
|
+
return {
|
|
1733
|
+
ok,
|
|
1734
|
+
currentLtv,
|
|
1735
|
+
newLtv,
|
|
1736
|
+
maxLtv,
|
|
1737
|
+
collateralUsd,
|
|
1738
|
+
currentDebt: currentDebtUsd,
|
|
1739
|
+
maxBorrow,
|
|
1740
|
+
message: ok ? void 0 : `ExceedsMaxLtv: borrowing $${borrowAmount} would push LTV to ${newLtv.toFixed(1)}% (max ${maxLtv}%). Collateral: $${collateralUsd.toFixed(2)}. Current debt: $${currentDebtUsd.toFixed(3)}. Max additional borrow: $${(maxBorrow - currentDebtUsd).toFixed(2)}. Deposit more collateral or borrow less.`
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1743
|
+
// ══════════════════════════════════════════
|
|
1511
1744
|
// Flow 3: Deposit collateral only
|
|
1512
1745
|
// ══════════════════════════════════════════
|
|
1513
1746
|
/**
|
|
@@ -1548,13 +1781,18 @@ var MorphoCreditClient = class {
|
|
|
1548
1781
|
const collateralWei = ethers4.parseUnits(collateralAmount, tokenInfo.decimals);
|
|
1549
1782
|
const borrowWei = ethers4.parseUnits(borrowAmount, 6);
|
|
1550
1783
|
const accountAddr = await this.getAccountAddress();
|
|
1784
|
+
const ltvCheck = await this.checkLtv(tokenSymbol, collateralAmount, borrowAmount);
|
|
1785
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1551
1786
|
const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
|
|
1552
1787
|
await this.ensureCreditProvider(accountAddr);
|
|
1553
|
-
const
|
|
1788
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1789
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
|
|
1790
|
+
const borrowTx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1791
|
+
await borrowTx.wait();
|
|
1554
1792
|
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1555
1793
|
return {
|
|
1556
1794
|
depositTx: depositTxHash,
|
|
1557
|
-
borrowTx:
|
|
1795
|
+
borrowTx: borrowTx.hash,
|
|
1558
1796
|
collateral: { amount: collateralWei, token: tokenSymbol },
|
|
1559
1797
|
borrowed: borrowWei,
|
|
1560
1798
|
agentAccount: accountAddr,
|
|
@@ -1585,10 +1823,16 @@ var MorphoCreditClient = class {
|
|
|
1585
1823
|
if (!activeToken) {
|
|
1586
1824
|
throw new Error("No collateral deposited. Use deposit() or depositAndBorrow() first.");
|
|
1587
1825
|
}
|
|
1588
|
-
const
|
|
1826
|
+
const ltvCheck = await this.checkLtv(activeToken.symbol, "0", amount);
|
|
1827
|
+
if (!ltvCheck.ok) throw new Error(ltvCheck.message);
|
|
1828
|
+
await this.ensureCreditProvider(accountAddr);
|
|
1829
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1830
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [activeToken.address, borrowWei]);
|
|
1831
|
+
const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1832
|
+
await tx.wait();
|
|
1589
1833
|
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1590
1834
|
return {
|
|
1591
|
-
tx:
|
|
1835
|
+
tx: tx.hash,
|
|
1592
1836
|
amount: borrowWei,
|
|
1593
1837
|
agentAccount: accountAddr,
|
|
1594
1838
|
totalDebt,
|
|
@@ -1633,8 +1877,11 @@ var MorphoCreditClient = class {
|
|
|
1633
1877
|
const borrowWei = ethers4.parseUnits(borrowAmount, 6);
|
|
1634
1878
|
try {
|
|
1635
1879
|
await this.ensureCreditProvider(accountAddr);
|
|
1636
|
-
const
|
|
1637
|
-
|
|
1880
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1881
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
|
|
1882
|
+
const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1883
|
+
await tx.wait();
|
|
1884
|
+
result.borrowTx = tx.hash;
|
|
1638
1885
|
result.borrowed = borrowWei;
|
|
1639
1886
|
} catch (e) {
|
|
1640
1887
|
throw new Error(`Borrow failed (caller may not own this AgentAccount): ${e.message}`);
|
|
@@ -1670,17 +1917,20 @@ var MorphoCreditClient = class {
|
|
|
1670
1917
|
if (balance < amountWei) {
|
|
1671
1918
|
throw new Error(`Insufficient USDC in AgentAccount: $${ethers4.formatUnits(balance, 6)}`);
|
|
1672
1919
|
}
|
|
1673
|
-
const
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1920
|
+
const txHash = await this.batch(accountAddr, [
|
|
1921
|
+
{
|
|
1922
|
+
target: this.config.contracts.usdc,
|
|
1923
|
+
value: 0n,
|
|
1924
|
+
data: this.erc20Iface.encodeFunctionData("approve", [this.config.contracts.morphoCredit, amountWei])
|
|
1925
|
+
},
|
|
1926
|
+
{
|
|
1927
|
+
target: this.config.contracts.morphoCredit,
|
|
1928
|
+
value: 0n,
|
|
1929
|
+
data: this.morphoIface.encodeFunctionData("repayWithCollateral", [collateralAddr, amountWei])
|
|
1930
|
+
}
|
|
1931
|
+
]);
|
|
1682
1932
|
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1683
|
-
return { tx:
|
|
1933
|
+
return { tx: txHash, amount: amountWei, remainingDebt: totalDebt };
|
|
1684
1934
|
}
|
|
1685
1935
|
/**
|
|
1686
1936
|
* Withdraw collateral from Morpho back to EOA.
|
|
@@ -1701,18 +1951,21 @@ var MorphoCreditClient = class {
|
|
|
1701
1951
|
`Cannot withdraw more than deposited: max ${ethers4.formatUnits(pos.collateralAmount, tokenInfo.decimals)} ${tokenSymbol}`
|
|
1702
1952
|
);
|
|
1703
1953
|
}
|
|
1704
|
-
const
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1954
|
+
const txHash = await this.batch(accountAddr, [
|
|
1955
|
+
{
|
|
1956
|
+
target: this.config.contracts.morphoCredit,
|
|
1957
|
+
value: 0n,
|
|
1958
|
+
data: this.morphoIface.encodeFunctionData("withdrawCollateral", [tokenInfo.address, withdrawAmount])
|
|
1959
|
+
},
|
|
1960
|
+
{
|
|
1961
|
+
target: tokenInfo.address,
|
|
1962
|
+
value: 0n,
|
|
1963
|
+
data: this.erc20Iface.encodeFunctionData("transfer", [this.signer.address, withdrawAmount])
|
|
1964
|
+
}
|
|
1965
|
+
]);
|
|
1713
1966
|
const newPos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1714
1967
|
return {
|
|
1715
|
-
tx:
|
|
1968
|
+
tx: txHash,
|
|
1716
1969
|
amount: withdrawAmount,
|
|
1717
1970
|
token: tokenSymbol,
|
|
1718
1971
|
destination: this.signer.address,
|
|
@@ -1777,6 +2030,17 @@ var MorphoCreditClient = class {
|
|
|
1777
2030
|
return this.signer.address;
|
|
1778
2031
|
}
|
|
1779
2032
|
};
|
|
2033
|
+
_MorphoCreditClient.ERC8004_ABI = [
|
|
2034
|
+
"function register(string agentURI) returns (uint256)",
|
|
2035
|
+
"function ownerOf(uint256 tokenId) view returns (address)",
|
|
2036
|
+
"function balanceOf(address owner) view returns (uint256)",
|
|
2037
|
+
"function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)"
|
|
2038
|
+
];
|
|
2039
|
+
// ══════════════════════════════════════════
|
|
2040
|
+
// LTV Pre-check
|
|
2041
|
+
// ══════════════════════════════════════════
|
|
2042
|
+
_MorphoCreditClient.ORACLE_ABI = ["function price() view returns (uint256)"];
|
|
2043
|
+
var MorphoCreditClient = _MorphoCreditClient;
|
|
1780
2044
|
|
|
1781
2045
|
// src/clients/WalletClient.ts
|
|
1782
2046
|
import { ethers as ethers5, Contract as Contract4, Wallet } from "ethers";
|