[Webfunds-commits] java/webfunds/client/sox SOXWallet.java
Ian Grigg
iang@cypherpunks.ai
Sun, 17 Sep 2000 16:30:30 -0400 (AST)
iang 00/09/17 16:30:30
Modified: webfunds/client/sox SOXWallet.java
Log:
1. split out makePurePayment into a WalletContext (AccountInfo) version
and a lower layer (accountId) one. Now need to change error() calls
in latter version into exceptions.
2. moved WalletContext and WalletManager to client/plugins.
Revision Changes Path
1.132 +166 -36 java/webfunds/client/sox/SOXWallet.java
Index: SOXWallet.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/client/sox/SOXWallet.java,v
retrieving revision 1.131
retrieving revision 1.132
diff -u -r1.131 -r1.132
--- SOXWallet.java 2000/09/03 16:51:51 1.131
+++ SOXWallet.java 2000/09/17 20:30:29 1.132
@@ -1,4 +1,4 @@
-/* $Id: SOXWallet.java,v 1.131 2000/09/03 16:51:51 iang Exp $
+/* $Id: SOXWallet.java,v 1.132 2000/09/17 20:30:29 iang Exp $
*
* Copyright (c) Systemics Inc. 1995-2000 on behalf of
* The WebFunds Development Team. All Rights Reserved.
@@ -15,17 +15,18 @@
import java.awt.event.ActionEvent;
import java.beans.*;
-import webfunds.client.AccountInfo;
-import webfunds.client.Addressbook;
-import webfunds.client.SepFileStore;
-import webfunds.client.Transaction;
-import webfunds.client.UInterface;
-import webfunds.client.WalletContext;
-import webfunds.client.WalletInterface;
-import webfunds.client.sox.StoreAccountStore;
+// SOX tool kit
import webfunds.ricardian.Contract;
import webfunds.ricardian.ContractStore;
import webfunds.ricardian.SOXServerException;
+
+import webfunds.utils.Debug;
+import webfunds.utils.Hex;
+import webfunds.utils.Panic;
+
+import webfunds.store.Store;
+import webfunds.store.StoreException;
+
import webfunds.sox.Account;
import webfunds.sox.AccountId;
import webfunds.sox.Armoury;
@@ -45,11 +46,16 @@
import webfunds.sox.SOXSubAccountException;
import webfunds.sox.SubAccount;
import webfunds.sox.ValueAccount;
-import webfunds.store.Store;
-import webfunds.store.StoreException;
-import webfunds.utils.Debug;
-import webfunds.utils.Hex;
-import webfunds.utils.Panic;
+
+// WebFunds Client Application
+import webfunds.client.AccountInfo;
+import webfunds.client.Addressbook;
+import webfunds.client.SepFileStore;
+import webfunds.client.Transaction;
+import webfunds.client.UInterface;
+import webfunds.client.plugins.WalletContext;
+import webfunds.client.WalletInterface;
+import webfunds.client.sox.StoreAccountStore;
/**
@@ -207,7 +213,7 @@
/**
* Set the Store.
- * This is the only access we have to secondary storage.
+ * This is the only access we have to persistant storage.
* Unfortunately, it's quite limiting.
*/
public void setStore(Store store)
@@ -448,7 +454,6 @@
/**
* Conversion between high level and low level.
*/
-// public Payment makePurePayment(AccountId source, AccountId target,
public Payment makePurePayment(AccountInfo source, AccountInfo target,
ItemId instrument, long amount,
byte[] description,
@@ -467,8 +472,6 @@
return makePurePayment(
src, tgt,
- // new AccountInfo(source.getId(), null, null),
- // new AccountInfo(target.getId(), null, null),
instrument,
amount,
description,
@@ -477,6 +480,21 @@
paymentId);
}
+ private boolean gotEnough(AccountId src,
+ ItemId contractid,
+ long amount)
+ {
+ long pend = getValue(src, contractid, true);
+ long confirmed = getValue(src, contractid, false);
+
+ logmsg("amount: " + amount + ", pend: " + pend +
+ ", confirmed: " + confirmed);
+
+ if ( (pend + confirmed) < amount )
+ return false;
+ else
+ return true;
+ }
/**
* Make a payment.
@@ -499,7 +517,6 @@
* @param till the time at which the payment will expire
* @param pid a payment identifier, ignored if empty
*/
-// public Payment makePurePayment(AccountInfo source, AccountInfo targetinfo,
public Payment makePurePayment(AccountId src, AccountId tgt,
ItemId contractid, long amount,
byte[] desc,
@@ -508,9 +525,8 @@
{
// Need a quiet non-GUI version: no AccountInfos, no error()'s !
-// AccountId tgt = new AccountId();
-// if (targetinfo != null)
-// tgt.setId(targetinfo.getId());
+ if (amount < 0)
+ throw new IllegalArgumentException("amount " + amount + " < 0 !");
Account acc;
try {
@@ -521,14 +537,7 @@
return null ;
}
- //checkIssuer(acc, contractid);
-
-// AccountId src = new AccountId();
-// src.setId(source.getId());
- long pend = getValue(src, contractid, true);
- long confirmed = getValue(src, contractid, false);
-
// it is an error (?) if the user asks for pid when
// that one is already in play.
if (pid != null && (pid.length() > 0))
@@ -547,14 +556,18 @@
}
-
- if ( amount > 0 &&
- ((pend + confirmed) < amount || confirmed < amount) )
+ /*
+ * Check if there is enough.
+ * (There is always "enough" if the src is equal to the target
+ * or if the amount is zero...)
+ */
+ if (!src.equals(tgt) && (amount > 0) &&
+ !gotEnough(src, contractid, amount))
{
- System.err.print("amount: " + amount);
- System.err.print(", pend: " + pend);
- System.err.println(", confirmed: " + confirmed);
-
+
+ /*
+ * Need to get the display amount into unit of account.
+ */
Contract contract = contracts.getContract(contractid);
double am = amount;
String name = contractid.toString();
@@ -620,7 +633,121 @@
return pay ;
}
+
/**
+ * Make a payment.
+ * This should be used by all automatic clients, it does:
+ * * access to subaccounts,
+ * * checks balances, and
+ * * saves the pending payment for later reconciliation.
+ * and delivers the payment back. It is thread safe.
+ *
+ * @param tgt the target account, may be bearer
+ * @param src the source account where funds are written from
+ * @param contractid is the name of the contract
+ * @param amount the (contract) qty of items of which the payment is for
+ * @param desc a description of what this payment is for (optional)
+ * @param boolean whether or not the payment is a rollover payment
+ * @param from the time from which the payment is valid
+ * @param till the time at which the payment will expire
+ * @param pid a payment identifier, ignored if empty
+ */
+ public synchronized Payment makeSafePayment(AccountId src, AccountId tgt,
+ ItemId contractid, long amount,
+ byte[] desc,
+ long from, long till,
+ String pid)
+ throws PaymentException
+ {
+ // A First Cut at a quiet non-GUI version
+
+ if (amount < 0)
+ throw new IllegalArgumentException("amount " + amount + " < 0 !");
+
+ Account acc;
+ try {
+ acc = getAccount(src);
+ } catch (StoreException ex) {
+ ex.printStackTrace();
+ throw new PaymentException(PaymentException.UNKNOWN_AC,
+ "Error getting account: " + ex);
+ }
+
+
+ // it is an error (?) if the user asks for pid when
+ // that one is already in play.
+ if (pid != null && (pid.length() > 0))
+ {
+ StateReceipt sr;
+ try {
+ sr = receiptStore.getReceipt(src, contractid, pid);
+ } catch (StoreException ex) {
+ throw new webfunds.utils.Panic("get StateReceipt for " + pid);
+ }
+ if (sr != null)
+ {
+ throw new PaymentException(PaymentException.PID_IN_USE, pid);
+ }
+ }
+
+
+ /*
+ * Check if there is enough.
+ * (There is always "enough" if the src is equal to the target
+ * or if the amount is zero... This is a judgement call of course.)
+ */
+ if (!src.equals(tgt) && (amount > 0) &&
+ !gotEnough(src, contractid, amount))
+ {
+ throw new PaymentException(PaymentException.NOT_ENUF_FUNDS,
+ "amount " + amount + " not available");
+ }
+
+ ValueAccount sub;
+ Payment pay;
+ try {
+ sub = (ValueAccount) acc.getSub(contractid);
+ if (sub == null)
+ {
+ throw new PaymentException(PaymentException.UNKNOWN_SUB,
+ "unknown: " + contractid);
+ }
+ pay = sub.createPayment(tgt, amount,
+ desc, false,
+ from, till,
+ pid);
+ } catch (SOXException ex) {
+ ex.printStackTrace();
+ throw new PaymentException(PaymentException.UNKNOWN,
+ "Payment no good: " + ex);
+ }
+
+ // this disappears when we get new better StateReceipts....
+ AccountInfo targetinfo = new AccountInfo(tgt.getId(), null, null);
+ AccountInfo sourceinfo = new AccountInfo(src.getId(), null, null);
+
+ //
+ // Have to create and store the PendingReceipt securely
+ // before returning the payment to the caller. Once
+ // returned, we have lost control of it, so must have the
+ // PendingReceipt receipt there for matching or cancelling.
+ //
+ PendingReceipt pending = new PendingReceipt(pay.getId(),
+ contractid,
+ sourceinfo, targetinfo,
+ amount, desc, new Date());
+ try {
+ receiptStore.addPendingReceipt(pending, src);
+ } catch (StoreException ex) {
+ ex.printStackTrace();
+ throw new PaymentException(PaymentException.UNKNOWN,
+ "Error saving Pending: " + ex);
+ }
+
+ return pay ;
+ }
+
+ /**
* Smart decoder.
*/
public byte[] decodeSOXPayment(byte[] payment)
@@ -1534,6 +1661,9 @@
/////////// Account / Contract manipulations ////////////////////////
+ /**
+ * Client Wallet Interface
+ */
public AccountInfo addAccount()
{