[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()
     {